From 005e0c4f83f1b690ef320510c60ab30883ee2b43 Mon Sep 17 00:00:00 2001
From: psiddharthdesign <107192927+psiddharthdesign@users.noreply.github.com>
Date: Sat, 27 Jul 2024 02:18:49 +0530
Subject: [PATCH] feature/run details
---
package.json | 4 +-
.../runs/[runId]/ProjectRunDetails.tsx | 342 ++++++++++++++++++
.../[projectSlug]/runs/[runId]/RunDetails.tsx | 80 ----
.../[projectSlug]/runs/[runId]/page.tsx | 36 +-
src/app/layout.tsx | 3 +-
src/data/user/projects.tsx | 17 +
src/data/user/runs.ts | 74 ++++
src/lib/database.types.ts | 35 +-
src/styles/globals.css | 10 +-
.../20240726135234_remote_schema.sql | 7 +
...726181205_add_terraform_column_to_runs.sql | 8 +
.../20240726184158_add_changes_to_runs.sql | 2 +
tailwind.config.cjs | 1 +
13 files changed, 522 insertions(+), 97 deletions(-)
create mode 100644 src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/runs/[runId]/ProjectRunDetails.tsx
delete mode 100644 src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/runs/[runId]/RunDetails.tsx
create mode 100644 supabase/migrations/20240726135234_remote_schema.sql
create mode 100644 supabase/migrations/20240726181205_add_terraform_column_to_runs.sql
create mode 100644 supabase/migrations/20240726184158_add_changes_to_runs.sql
diff --git a/package.json b/package.json
index 556610c9..3bd30226 100644
--- a/package.json
+++ b/package.json
@@ -185,8 +185,8 @@
"dev:debug": "NODE_OPTIONS='--inspect' next dev",
"email:dev": "email dev",
"start": "next start",
- "generate:types": "supabase gen types typescript --linked --schema public > src/lib/database.types.ts",
- "generate:types:local": "supabase gen types typescript --local > src/lib/database.types.ts",
+ "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",
"build": "next build",
"test:e2e": "cross-env NODE_ENV=test playwright test",
"test:e2e:ui": "cross-env NODE_ENV=test playwright test --ui",
diff --git a/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/runs/[runId]/ProjectRunDetails.tsx b/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/runs/[runId]/ProjectRunDetails.tsx
new file mode 100644
index 00000000..e1db78f5
--- /dev/null
+++ b/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/runs/[runId]/ProjectRunDetails.tsx
@@ -0,0 +1,342 @@
+'use client';
+
+import { T } from "@/components/ui/Typography";
+import { Badge } from "@/components/ui/badge";
+import { Button } from "@/components/ui/button";
+import { Card, CardContent } from "@/components/ui/card";
+import { approveRun, changeRunStatus, rejectRun } from "@/data/user/runs";
+import { useSAToastMutation } from "@/hooks/useSAToastMutation";
+import { Table } from "@/types";
+import { DotFilledIcon } from "@radix-ui/react-icons";
+import { AnimatePresence, motion } from 'framer-motion';
+import { CheckCircle2, Clock, GitPullRequest, Loader2, Play, XCircle } from 'lucide-react';
+import Image from 'next/image';
+import { useRouter } from 'next/navigation';
+import React, { useEffect, useState } from 'react';
+import { statusColors } from "../../(specific-project-pages)/RunsTable";
+
+type RunStage = 'pending_approval' | 'pending_apply' | 'rejected' | 'applied';
+
+
+const logEntries = [
+ { time: "2024-07-01T12:34:56Z", author: "Siddharth Ponnapalli", title: "Added basic VPC setup" },
+ { time: "2024-07-01T13:45:22Z", author: "Siddharth Ponnapalli", title: "Added subnets and associated them with VPC" },
+ { time: "2024-07-02T09:14:33Z", author: "Siddharth Ponnapalli", title: "Created security groups for web servers" },
+ { time: "2024-07-02T10:22:12Z", author: "Siddharth Ponnapalli", title: "Added EC2 instances in different subnets" },
+ { time: "2024-07-03T11:55:47Z", author: "Siddharth Ponnapalli", title: "Configured S3 buckets and objects" },
+ { time: "2024-07-03T14:33:29Z", author: "Siddharth Ponnapalli", title: "Added RDS instance with MySQL" },
+ { time: "2024-07-04T08:45:22Z", author: "Siddharth Ponnapalli", title: "Created IAM role, policy, and instance profile" },
+ { time: "2024-07-04T10:12:09Z", author: "Siddharth Ponnapalli", title: "Added third EC2 instance with IAM role" },
+ { time: "2024-07-05T11:34:56Z", author: "Siddharth Ponnapalli", title: "Updated security group rules for enhanced security" },
+ { time: "2024-07-05T13:45:22Z", author: "Siddharth Ponnapalli", title: "Refactored subnet CIDR blocks for better segmentation" },
+ { time: "2024-07-06T09:14:33Z", author: "Siddharth Ponnapalli", title: "Improved S3 bucket policies for enhanced security" },
+ { time: "2024-07-06T10:22:12Z", author: "Siddharth Ponnapalli", title: "Added outputs for easier infrastructure management" },
+ { time: "2024-07-07T11:55:47Z", author: "Siddharth Ponnapalli", title: "Enhanced instance tagging for better identification" },
+ { time: "2024-07-07T14:33:29Z", author: "Siddharth Ponnapalli", title: "Updated RDS instance settings for improved performance" },
+ { time: "2024-07-08T08:45:22Z", author: "Siddharth Ponnapalli", title: "Optimized VPC and subnet configurations" },
+ { time: "2024-07-08T10:12:09Z", author: "Siddharth Ponnapalli", title: "Cleaned up IAM policies for better security practices" },
+ { time: "2024-07-09T11:34:56Z", author: "Siddharth Ponnapalli", title: "Added new S3 bucket for log storage" },
+ { time: "2024-07-09T13:45:22Z", author: "Siddharth Ponnapalli", title: "Implemented CloudWatch logs for monitoring" },
+ { time: "2024-07-10T09:14:33Z", author: "Siddharth Ponnapalli", title: "Configured CloudFront distribution for S3 bucket" },
+ { time: "2024-07-10T10:22:12Z", author: "Siddharth Ponnapalli", title: "Added Route 53 records for domain management" },
+ { time: "2024-07-11T11:55:47Z", author: "Siddharth Ponnapalli", title: "Updated EC2 instance types for better performance" },
+ { time: "2024-07-11T14:33:29Z", author: "Siddharth Ponnapalli", title: "Refined security group rules for better protection" },
+ { time: "2024-07-12T08:45:22Z", author: "Siddharth Ponnapalli", title: "Added auto-scaling configuration for EC2 instances" },
+ { time: "2024-07-12T10:12:09Z", author: "Siddharth Ponnapalli", title: "Configured RDS backup and retention policies" },
+ { time: "2024-07-13T11:34:56Z", author: "Siddharth Ponnapalli", title: "Updated IAM role policies for least privilege access" },
+ { time: "2024-07-13T13:45:22Z", author: "Siddharth Ponnapalli", title: "Implemented Lambda function for automated backups" },
+ { time: "2024-07-14T09:14:33Z", author: "Siddharth Ponnapalli", title: "Integrated CloudWatch alarms for monitoring" },
+ { time: "2024-07-14T10:22:12Z", author: "Siddharth Ponnapalli", title: "Updated S3 bucket lifecycle policies for cost optimization" },
+ { time: "2024-07-15T11:55:47Z", author: "Siddharth Ponnapalli", title: "Configured VPC peering for multi-region setup" },
+ { time: "2024-07-15T14:33:29Z", author: "Siddharth Ponnapalli", title: "Enhanced CloudFront caching settings" },
+ { time: "2024-07-16T08:45:22Z", author: "Siddharth Ponnapalli", title: "Added new security group for database access" },
+ { time: "2024-07-16T10:12:09Z", author: "Siddharth Ponnapalli", title: "Updated RDS instance class for better performance" },
+ { time: "2024-07-17T11:34:56Z", author: "Siddharth Ponnapalli", title: "Implemented SNS for notification alerts" },
+ { time: "2024-07-17T13:45:22Z", author: "Siddharth Ponnapalli", title: "Configured SES for email notifications" },
+ { time: "2024-07-18T09:14:33Z", author: "Siddharth Ponnapalli", title: "Added DynamoDB table for session management" },
+ { time: "2024-07-18T10:22:12Z", author: "Siddharth Ponnapalli", title: "Updated IAM policies for DynamoDB access" },
+ { time: "2024-07-19T11:55:47Z", author: "Siddharth Ponnapalli", title: "Enhanced EC2 instance monitoring with detailed metrics" },
+ { time: "2024-07-19T14:33:29Z", author: "Siddharth Ponnapalli", title: "Configured VPC flow logs for network monitoring" },
+ { time: "2024-07-20T08:45:22Z", author: "Siddharth Ponnapalli", title: "Updated security group ingress rules for specific IP ranges" },
+ { time: "2024-07-20T10:12:09Z", author: "Siddharth Ponnapalli", title: "Added IAM policy for S3 read-only access" },
+ { time: "2024-07-21T11:34:56Z", author: "Siddharth Ponnapalli", title: "Refined Lambda function code for efficiency" },
+ { time: "2024-07-21T13:45:22Z", author: "Siddharth Ponnapalli", title: "Enhanced VPC subnet configuration for better isolation" },
+ { time: "2024-07-22T09:14:33Z", author: "Siddharth Ponnapalli", title: "Configured CloudFormation stack for infrastructure as code" },
+ { time: "2024-07-22T10:22:12Z", author: "Siddharth Ponnapalli", title: "Updated EC2 instance AMI for latest security patches" },
+ { time: "2024-07-23T11:55:47Z", author: "Siddharth Ponnapalli", title: "Implemented SSM for instance management" },
+ { time: "2024-07-23T14:33:29Z", author: "Siddharth Ponnapalli", title: "Enhanced IAM roles for cross-account access" },
+ { time: "2024-07-24T08:45:22Z", author: "Siddharth Ponnapalli", title: "Configured RDS read replicas for high availability" },
+ { time: "2024-07-24T10:12:09Z", author: "Siddharth Ponnapalli", title: "Added CloudFront invalidation for cache management" },
+ { time: "2024-07-25T11:34:56Z", author: "Siddharth Ponnapalli", title: "Updated Route 53 health checks for better uptime monitoring" },
+ { time: "2024-07-25T13:45:22Z", author: "Siddharth Ponnapalli", title: "Enhanced S3 bucket encryption settings for data security" },
+ { time: "2024-07-26T09:14:33Z", author: "Siddharth Ponnapalli", title: "Configured ELB for load balancing EC2 instances" },
+ { time: "2024-07-26T10:22:12Z", author: "Siddharth Ponnapalli", title: "Updated IAM policies for better resource access control" },
+ { time: "2024-07-27T11:55:47Z", author: "Siddharth Ponnapalli", title: "Enhanced CloudWatch dashboards for better visibility" },
+ { time: "2024-07-27T14:33:29Z", author: "Siddharth Ponnapalli", title: "Configured EC2 instance user data for automation" }
+];
+
+
+function RenderContent({
+ activeStage,
+ run,
+}: {
+ activeStage: string;
+ run: Table<'digger_runs'>;
+}) {
+ if (activeStage === 'plan') {
+ return (
+
+
Terraform Plan Output
+
+ {run.terraform_output || 'No plan output available'}
+
+
+ );
+ } else if (activeStage === 'apply') {
+ if (run.status === 'pending_approval' || run.status === 'rejected') {
+ return (
+
+
+
Apply not available
+
The run needs to be approved before applying changes.
+
+
+ );
+ }
+ return (
+
+
Apply logs
+
+ {logEntries.map((log, index) => (
+
+
{log.time}
+
{log.author}
+
{log.title}
+
+ ))}
+
+
+ );
+ }
+}
+
+
+export const ProjectRunDetails: React.FC<{
+ run: Table<'digger_runs'>,
+ loggedInUser: Table<'user_profiles'>
+ isUserOrgAdmin: boolean
+}> = ({ run, loggedInUser, isUserOrgAdmin }) => {
+ const router = useRouter();
+ const [activeStage, setActiveStage] = useState<'plan' | 'apply'>('plan');
+ const [applyLogs, setApplyLogs] = useState([]);
+
+ useEffect(() => {
+ if (run.status === 'pending_apply') {
+ const timer = setTimeout(async () => {
+ await changeRunStatus(run.id, 'applied');
+ setActiveStage('apply');
+ router.refresh();
+ }, 5000);
+
+ return () => clearTimeout(timer);
+ }
+ }, [run.status, run.id, router]);
+
+ useEffect(() => {
+ if (run.apply_logs) {
+ setApplyLogs(run.apply_logs.split('\n'));
+ }
+ }, [run.apply_logs]);
+
+ const { mutate: approveMutation, isLoading: isApproving } = useSAToastMutation(
+ async () => await approveRun(run.id, loggedInUser.id),
+ {
+ loadingMessage: 'Approving run...',
+ successMessage: 'Run approved successfully',
+ errorMessage: 'Failed to approve run',
+ onSuccess: () => {
+ router.refresh();
+ },
+ }
+ );
+
+ const { mutate: rejectMutation, isLoading: isRejecting } = useSAToastMutation(
+ async () => await rejectRun(run.id, loggedInUser.id),
+ {
+ loadingMessage: 'Rejecting run...',
+ successMessage: 'Run rejected successfully',
+ errorMessage: 'Failed to reject run',
+ onSuccess: () => {
+ router.refresh();
+ },
+ }
+ );
+
+
+
+ return (
+
+
+
+ Run Details
+
+
+
+
+
+
+ {run.status.toUpperCase()}
+
+ } />
+ {run.pr_number && }
+
+
+
+
+
}
+ name="Plan"
+ isActive={activeStage === 'plan'}
+ isComplete={run.status !== 'pending_approval'}
+ onClick={() => setActiveStage('plan')}
+ />
+ {run.status === 'pending_approval' && isUserOrgAdmin && (
+
+
+ Do you approve the proposed changes?
+
+
+
+
+
+
+ )}
+
}
+ name="Apply"
+ isActive={activeStage === 'apply'}
+ isComplete={run.status === 'applied'}
+ isDisabled={run.status === 'pending_approval' || run.status === 'rejected'}
+ onClick={() => setActiveStage('apply')}
+ />
+
+ {run.status === 'pending_apply' && run.is_approved && (
+
+
+ Applying changes...
+
+ )}
+
+ {run.is_approved && run.status !== 'rejected' || 'pending_approval' && (
+ Approved by:
+ )}
+ {run.status === 'rejected' && (
+ Rejected by:
+ )}
+ {(run.status === 'pending_apply' || run.status === 'applied' || run.status === 'rejected') && (
+
+
+ {loggedInUser.avatar_url ? (
+
+ ) : (
+
+ {loggedInUser.full_name?.charAt(0).toUpperCase() || 'A'}
+
+ )}
+
+
+
{loggedInUser.full_name}
+
+ {isUserOrgAdmin ? 'Organization Admin' : 'Member'}
+
+
+
+
+ )}
+
+
+
+
+
+
+ );
+};
+
+const RunStage: React.FC<{
+ icon: React.ReactNode,
+ name: string,
+ isActive: boolean,
+ isComplete: boolean,
+ isDisabled?: boolean,
+ onClick: () => void
+}> = ({ icon, name, isActive, isComplete, isDisabled = false, onClick }) => (
+
+
+ {isActive && !isComplete && }
+ {isComplete && }
+
+);
+
+const DetailItem: React.FC<{ label: string, value: string | React.ReactNode }> = ({ label, value }) => (
+
+
{label}:
+ {typeof value === 'string' ?
{value}
: value}
+
+);
\ No newline at end of file
diff --git a/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/runs/[runId]/RunDetails.tsx b/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/runs/[runId]/RunDetails.tsx
deleted file mode 100644
index e60583ac..00000000
--- a/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/runs/[runId]/RunDetails.tsx
+++ /dev/null
@@ -1,80 +0,0 @@
-'use client';
-
-import { Badge } from "@/components/ui/badge";
-import { Button } from "@/components/ui/button";
-import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
-import { Tables } from "@/lib/database.types";
-import { AnimatePresence, motion } from 'framer-motion';
-import { ChevronDown } from 'lucide-react';
-import React, { useState } from 'react';
-import { statusColors } from "../../(specific-project-pages)/RunsTable";
-
-export const RunDetails: React.FC<{ run: Tables<'digger_runs'> }> = ({ run }) => {
- const [isExpanded, setIsExpanded] = useState(false);
-
- return (
-
-
-
-
- Run {run.id}
-
-
- {run.status.toUpperCase()}
-
-
-
-
-
-
Commit: {run.commit_id}
-
Date: {run.created_at}
-
-
-
-
- {isExpanded && run.status && (
-
- Plan Summary
-
-
- {run.status}
- Created
-
-
- {run.status}
- Updated
-
-
- {run.status}
- Deleted
-
-
-
- )}
-
-
-
-
- );
-};
diff --git a/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/runs/[runId]/page.tsx b/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/runs/[runId]/page.tsx
index bd604628..c862c521 100644
--- a/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/runs/[runId]/page.tsx
+++ b/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/runs/[runId]/page.tsx
@@ -1,13 +1,18 @@
import { PageHeading } from "@/components/PageHeading";
import { T } from "@/components/ui/Typography";
+import { getLoggedInUserOrganizationRole } from "@/data/user/organizations";
+import { getSlimProjectById } from "@/data/user/projects";
import { getRunById } from "@/data/user/runs";
+import { getUserProfile } from "@/data/user/user";
+import { Table } from "@/types";
+import { serverGetLoggedInUser } from "@/utils/server/serverGetLoggedInUser";
import {
runIdParamSchema
} from "@/utils/zod-schemas/params";
import type { Metadata } from "next";
-import { Suspense } from "react";
-import { RunDetails } from "./RunDetails";
+import dynamic from 'next/dynamic';
+import { ComponentType, Suspense } from "react";
export const metadata: Metadata = {
title: "Projects",
@@ -20,6 +25,19 @@ type RunDetailPageProps = {
};
};
+type ProjectRunDetailsProps = {
+ run: Table<'digger_runs'>,
+ loggedInUser: Table<'user_profiles'>,
+ isUserOrgAdmin: boolean
+}
+
+
+
+const DynamicProjectRunDetails = dynamic(() =>
+ import('./ProjectRunDetails').then((mod) => mod.ProjectRunDetails as ComponentType),
+ { ssr: false }
+)
+
export default async function RunDetailPage({
params,
@@ -27,15 +45,23 @@ export default async function RunDetailPage({
}: RunDetailPageProps) {
const { runId } = runIdParamSchema.parse(params);
const run = await getRunById(runId);
+ const project_id = run.project_id;
+ const [project, user] = await Promise.all([
+ getSlimProjectById(project_id),
+ serverGetLoggedInUser()
+ ]);
+ const userProfile = await getUserProfile(user.id);
+ const organizationRole = await getLoggedInUserOrganizationRole(project.organization_id);
+ const isOrganizationAdmin =
+ organizationRole === "admin" || organizationRole === "owner";
return (
-
+
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index 6998ca25..c457c761 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -1,5 +1,6 @@
import '@/styles/globals.css';
import '@/styles/prosemirror.css';
+import { GeistMono } from 'geist/font/mono';
import { GeistSans } from 'geist/font/sans';
import { Metadata } from 'next';
import 'server-only';
@@ -22,7 +23,7 @@ export default async function RootLayout({
children: React.ReactNode;
}) {
return (
-
+
{children}
diff --git a/src/data/user/projects.tsx b/src/data/user/projects.tsx
index 5f351431..2c2f68cd 100644
--- a/src/data/user/projects.tsx
+++ b/src/data/user/projects.tsx
@@ -346,4 +346,21 @@ export async function updateProjectSettingsAction({
console.error("Error updating project settings:", error);
return { status: 'error', message: 'Failed to update project settings' };
}
+}
+
+export async function deleteProject(projectId: string): Promise
> {
+ const supabase = createSupabaseUserServerComponentClient();
+ const { data, error } = await supabase
+ .from('projects')
+ .update({
+ deleted_at: new Date().toISOString(),
+ })
+ .eq('id', projectId)
+ .single();
+
+ if (error) {
+ return { status: 'error', message: error.message };
+ }
+
+ return { status: 'success', data };
}
\ No newline at end of file
diff --git a/src/data/user/runs.ts b/src/data/user/runs.ts
index 40b2e24c..f4585578 100644
--- a/src/data/user/runs.ts
+++ b/src/data/user/runs.ts
@@ -1,6 +1,7 @@
'use server';
import { createSupabaseUserServerComponentClient } from '@/supabase-clients/user/createSupabaseUserServerComponentClient';
+import { SAPayload } from '@/types';
export async function getTFVarsByProjectId(projectId: string) {
const supabaseClient = createSupabaseUserServerComponentClient();
@@ -122,3 +123,76 @@ export async function getRunsByProjectId(projectId: string) {
if (error) throw error;
return data;
}
+
+export async function requestRunApproval(
+ runId: string,
+): Promise> {
+ const supabase = createSupabaseUserServerComponentClient();
+ const { data, error } = await supabase
+ .from('digger_runs')
+ .update({ status: 'pending_approval' })
+ .eq('id', runId)
+ .select('id')
+ .single();
+
+ if (error) {
+ return { status: 'error', message: error.message };
+ }
+ return { status: 'success', data: data.id };
+}
+
+export async function approveRun(
+ runId: string,
+ userId: string,
+): Promise> {
+ const supabase = createSupabaseUserServerComponentClient();
+ const { data, error } = await supabase
+ .from('digger_runs')
+ .update({
+ status: 'pending_apply',
+ approver_user_id: userId,
+ is_approved: true,
+ })
+ .eq('id', runId)
+ .select('id')
+ .single();
+
+ if (error) {
+ return { status: 'error', message: error.message };
+ }
+ return { status: 'success', data: data.id };
+}
+
+export async function rejectRun(
+ runId: string,
+ userId: string,
+): Promise> {
+ const supabase = createSupabaseUserServerComponentClient();
+ const { data, error } = await supabase
+ .from('digger_runs')
+ .update({
+ status: 'rejected',
+ approver_user_id: userId,
+ is_approved: false,
+ })
+ .eq('id', runId)
+ .select('id')
+ .single();
+
+ if (error) {
+ return { status: 'error', message: error.message };
+ }
+ return { status: 'success', data: data.id };
+}
+
+export async function changeRunStatus(runId: string, status: string) {
+ const supabase = createSupabaseUserServerComponentClient();
+ const { error } = await supabase
+ .from('digger_runs')
+ .update({ status: status })
+ .eq('id', runId)
+ .select('id')
+ .single();
+
+ if (error) throw error;
+}
diff --git a/src/lib/database.types.ts b/src/lib/database.types.ts
index 93568bdd..6aa0a1e3 100644
--- a/src/lib/database.types.ts
+++ b/src/lib/database.types.ts
@@ -208,7 +208,7 @@ export type Database = {
deleted_at: string | null
expiry: string | null
id: number
- organisation_id: number | null
+ organisation_id: string | null
type: string | null
updated_at: string | null
value: string | null
@@ -218,7 +218,7 @@ export type Database = {
deleted_at?: string | null
expiry?: string | null
id?: number
- organisation_id?: number | null
+ organisation_id?: string | null
type?: string | null
updated_at?: string | null
value?: string | null
@@ -228,12 +228,20 @@ export type Database = {
deleted_at?: string | null
expiry?: string | null
id?: number
- organisation_id?: number | null
+ organisation_id?: string | null
type?: string | null
updated_at?: string | null
value?: string | null
}
- Relationships: []
+ Relationships: [
+ {
+ foreignKeyName: "fk_jt_organisation_id"
+ columns: ["organisation_id"]
+ isOneToOne: false
+ referencedRelation: "organizations"
+ referencedColumns: ["id"]
+ },
+ ]
}
digger_jobs: {
Row: {
@@ -403,9 +411,11 @@ export type Database = {
}
digger_runs: {
Row: {
+ apply_logs: string | null
apply_stage_id: string | null
approval_author: string | null
approval_date: string | null
+ approver_user_id: string | null
commit_id: string
created_at: string
deleted_at: string | null
@@ -415,17 +425,21 @@ export type Database = {
is_approved: boolean | null
plan_stage_id: string | null
pr_number: number | null
+ project_id: string
project_name: string | null
repo_id: number
run_type: string
status: string
+ terraform_output: string | null
triggertype: string
updated_at: string
}
Insert: {
+ apply_logs?: string | null
apply_stage_id?: string | null
approval_author?: string | null
approval_date?: string | null
+ approver_user_id?: string | null
commit_id: string
created_at?: string
deleted_at?: string | null
@@ -435,17 +449,21 @@ export type Database = {
is_approved?: boolean | null
plan_stage_id?: string | null
pr_number?: number | null
+ project_id: string
project_name?: string | null
repo_id?: number
run_type: string
status: string
+ terraform_output?: string | null
triggertype: string
updated_at?: string
}
Update: {
+ apply_logs?: string | null
apply_stage_id?: string | null
approval_author?: string | null
approval_date?: string | null
+ approver_user_id?: string | null
commit_id?: string
created_at?: string
deleted_at?: string | null
@@ -455,10 +473,12 @@ export type Database = {
is_approved?: boolean | null
plan_stage_id?: string | null
pr_number?: number | null
+ project_id?: string
project_name?: string | null
repo_id?: number
run_type?: string
status?: string
+ terraform_output?: string | null
triggertype?: string
updated_at?: string
}
@@ -477,6 +497,13 @@ export type Database = {
referencedRelation: "digger_run_stages"
referencedColumns: ["id"]
},
+ {
+ foreignKeyName: "fk_digger_runs_project"
+ columns: ["project_id"]
+ isOneToOne: false
+ referencedRelation: "projects"
+ referencedColumns: ["id"]
+ },
{
foreignKeyName: "fk_digger_runs_repo"
columns: ["repo_id"]
diff --git a/src/styles/globals.css b/src/styles/globals.css
index a8a3233b..100df39e 100644
--- a/src/styles/globals.css
+++ b/src/styles/globals.css
@@ -22,10 +22,10 @@
--destructive-foreground: 0 0% 98%;
--border: 240 5.9% 90%;
--input: 240 5.9% 90%;
- --ring: 240 10% 3.9%;
+ --ring: 240 5.9% 10%;
--radius: 0.5rem;
- --chart-1: 173 58% 39%;
- --chart-2: 12 76% 61%;
+ --chart-1: 12 76% 61%;
+ --chart-2: 173 58% 39%;
--chart-3: 197 37% 24%;
--chart-4: 43 74% 66%;
--chart-5: 27 87% 67%;
@@ -52,10 +52,10 @@
--input: 240 3.7% 15.9%;
--ring: 240 4.9% 83.9%;
--chart-1: 220 70% 50%;
- --chart-5: 160 60% 45%;
+ --chart-2: 160 60% 45%;
--chart-3: 30 80% 55%;
--chart-4: 280 65% 60%;
- --chart-2: 340 75% 55%;
+ --chart-5: 340 75% 55%;
}
}
diff --git a/supabase/migrations/20240726135234_remote_schema.sql b/supabase/migrations/20240726135234_remote_schema.sql
new file mode 100644
index 00000000..7e9f4d77
--- /dev/null
+++ b/supabase/migrations/20240726135234_remote_schema.sql
@@ -0,0 +1,7 @@
+drop index if exists "public"."idx_digger_runs_approval_status";
+
+alter table "public"."digger_runs" drop column "approval_status";
+
+drop type "public"."digger_run_approval_status";
+
+
diff --git a/supabase/migrations/20240726181205_add_terraform_column_to_runs.sql b/supabase/migrations/20240726181205_add_terraform_column_to_runs.sql
new file mode 100644
index 00000000..e544a795
--- /dev/null
+++ b/supabase/migrations/20240726181205_add_terraform_column_to_runs.sql
@@ -0,0 +1,8 @@
+ALTER TABLE "public"."digger_runs"
+ADD COLUMN "terraform_output" text;
+
+ALTER TABLE "public"."digger_runs"
+ADD COLUMN "apply_logs" text;
+
+ALTER TABLE "public"."digger_runs"
+ADD COLUMN "approver_user_id" uuid NULL;
\ No newline at end of file
diff --git a/supabase/migrations/20240726184158_add_changes_to_runs.sql b/supabase/migrations/20240726184158_add_changes_to_runs.sql
new file mode 100644
index 00000000..af0da71a
--- /dev/null
+++ b/supabase/migrations/20240726184158_add_changes_to_runs.sql
@@ -0,0 +1,2 @@
+ALTER TABLE "public"."digger_runs"
+ALTER COLUMN "project_id" SET NOT NULL
diff --git a/tailwind.config.cjs b/tailwind.config.cjs
index 897db6c0..18acb7f0 100644
--- a/tailwind.config.cjs
+++ b/tailwind.config.cjs
@@ -59,6 +59,7 @@ module.exports = {
fontFamily: {
sans: ['var(--font-satoshi)'],
display: ['Lexend', ...defaultTheme.fontFamily.sans],
+ mono: ['var(--font-geist-mono)'],
},
keyframes: {
accordionDown: {