mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
Merge branch 'feat/add-gitea-repo' of https://github.com/jrparks/dokploy into feat/add-gitea-repo
This commit is contained in:
@@ -27,6 +27,7 @@ if (typeof window === "undefined") {
|
|||||||
const baseApp: ApplicationNested = {
|
const baseApp: ApplicationNested = {
|
||||||
applicationId: "",
|
applicationId: "",
|
||||||
herokuVersion: "",
|
herokuVersion: "",
|
||||||
|
cleanCache: false,
|
||||||
watchPaths: [],
|
watchPaths: [],
|
||||||
applicationStatus: "done",
|
applicationStatus: "done",
|
||||||
appName: "",
|
appName: "",
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { expect, test } from "vitest";
|
|||||||
const baseApp: ApplicationNested = {
|
const baseApp: ApplicationNested = {
|
||||||
applicationId: "",
|
applicationId: "",
|
||||||
herokuVersion: "",
|
herokuVersion: "",
|
||||||
|
cleanCache: false,
|
||||||
applicationStatus: "done",
|
applicationStatus: "done",
|
||||||
appName: "",
|
appName: "",
|
||||||
autoDeploy: true,
|
autoDeploy: true,
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const AddRedirectchema = z.object({
|
const AddRedirectchema = z.object({
|
||||||
replicas: z.number(),
|
replicas: z.number().min(1, "Replicas must be at least 1"),
|
||||||
registryId: z.string(),
|
registryId: z.string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -130,9 +130,11 @@ export const ShowClusterSettings = ({ applicationId }: Props) => {
|
|||||||
placeholder="1"
|
placeholder="1"
|
||||||
{...field}
|
{...field}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
field.onChange(Number(e.target.value));
|
const value = e.target.value;
|
||||||
|
field.onChange(value === "" ? 0 : Number(value));
|
||||||
}}
|
}}
|
||||||
type="number"
|
type="number"
|
||||||
|
value={field.value || ""}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import { toast } from "sonner";
|
|||||||
import { domain } from "@/server/db/validations/domain";
|
import { domain } from "@/server/db/validations/domain";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { Dices } from "lucide-react";
|
import { Dices } from "lucide-react";
|
||||||
|
import Link from "next/link";
|
||||||
import type z from "zod";
|
import type z from "zod";
|
||||||
|
|
||||||
type Domain = z.infer<typeof domain>;
|
type Domain = z.infer<typeof domain>;
|
||||||
@@ -83,6 +84,13 @@ export const AddDomain = ({
|
|||||||
const { mutateAsync: generateDomain, isLoading: isLoadingGenerate } =
|
const { mutateAsync: generateDomain, isLoading: isLoadingGenerate } =
|
||||||
api.domain.generateDomain.useMutation();
|
api.domain.generateDomain.useMutation();
|
||||||
|
|
||||||
|
const { data: canGenerateTraefikMeDomains } =
|
||||||
|
api.domain.canGenerateTraefikMeDomains.useQuery({
|
||||||
|
serverId: application?.serverId || "",
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("canGenerateTraefikMeDomains", canGenerateTraefikMeDomains);
|
||||||
|
|
||||||
const form = useForm<Domain>({
|
const form = useForm<Domain>({
|
||||||
resolver: zodResolver(domain),
|
resolver: zodResolver(domain),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
@@ -186,6 +194,21 @@ export const AddDomain = ({
|
|||||||
name="host"
|
name="host"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
|
{!canGenerateTraefikMeDomains &&
|
||||||
|
field.value.includes("traefik.me") && (
|
||||||
|
<AlertBlock type="warning">
|
||||||
|
You need to set an IP address in your{" "}
|
||||||
|
<Link
|
||||||
|
href="/dashboard/settings/server"
|
||||||
|
className="text-primary"
|
||||||
|
>
|
||||||
|
{application?.serverId
|
||||||
|
? "Remote Servers -> Server -> Edit Server -> Update IP Address"
|
||||||
|
: "Web Server -> Server -> Update Server IP"}
|
||||||
|
</Link>{" "}
|
||||||
|
to make your traefik.me domain work.
|
||||||
|
</AlertBlock>
|
||||||
|
)}
|
||||||
<FormLabel>Host</FormLabel>
|
<FormLabel>Host</FormLabel>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<FormControl>
|
<FormControl>
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ import {
|
|||||||
Ban,
|
Ban,
|
||||||
CheckCircle2,
|
CheckCircle2,
|
||||||
Hammer,
|
Hammer,
|
||||||
HelpCircle,
|
|
||||||
RefreshCcw,
|
RefreshCcw,
|
||||||
|
Rocket,
|
||||||
Terminal,
|
Terminal,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
@@ -55,7 +55,7 @@ export const ShowGeneralApplication = ({ applicationId }: Props) => {
|
|||||||
<CardTitle className="text-xl">Deploy Settings</CardTitle>
|
<CardTitle className="text-xl">Deploy Settings</CardTitle>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="flex flex-row gap-4 flex-wrap">
|
<CardContent className="flex flex-row gap-4 flex-wrap">
|
||||||
<TooltipProvider delayDuration={0}>
|
<TooltipProvider delayDuration={0} disableHoverableContent={false}>
|
||||||
<DialogAction
|
<DialogAction
|
||||||
title="Deploy Application"
|
title="Deploy Application"
|
||||||
description="Are you sure you want to deploy this application?"
|
description="Are you sure you want to deploy this application?"
|
||||||
@@ -79,12 +79,14 @@ export const ShowGeneralApplication = ({ applicationId }: Props) => {
|
|||||||
<Button
|
<Button
|
||||||
variant="default"
|
variant="default"
|
||||||
isLoading={data?.applicationStatus === "running"}
|
isLoading={data?.applicationStatus === "running"}
|
||||||
className="flex items-center gap-1.5"
|
className="flex items-center gap-1.5 group focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
>
|
>
|
||||||
Deploy
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<HelpCircle className="size-4 text-muted-foreground hover:text-foreground transition-colors cursor-pointer" />
|
<div className="flex items-center">
|
||||||
|
<Rocket className="size-4 mr-1" />
|
||||||
|
Deploy
|
||||||
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipPrimitive.Portal>
|
<TooltipPrimitive.Portal>
|
||||||
<TooltipContent sideOffset={5} className="z-[60]">
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
@@ -114,9 +116,24 @@ export const ShowGeneralApplication = ({ applicationId }: Props) => {
|
|||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Button variant="secondary" isLoading={isReloading}>
|
<Button
|
||||||
Reload
|
variant="secondary"
|
||||||
<RefreshCcw className="size-4" />
|
isLoading={isReloading}
|
||||||
|
className="flex items-center gap-1.5 group focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
|
>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<div className="flex items-center">
|
||||||
|
<RefreshCcw className="size-4 mr-1" />
|
||||||
|
Reload
|
||||||
|
</div>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipPrimitive.Portal>
|
||||||
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
|
<p>Reload the application without rebuilding it</p>
|
||||||
|
</TooltipContent>
|
||||||
|
</TooltipPrimitive.Portal>
|
||||||
|
</Tooltip>
|
||||||
</Button>
|
</Button>
|
||||||
</DialogAction>
|
</DialogAction>
|
||||||
<DialogAction
|
<DialogAction
|
||||||
@@ -139,13 +156,14 @@ export const ShowGeneralApplication = ({ applicationId }: Props) => {
|
|||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
isLoading={data?.applicationStatus === "running"}
|
isLoading={data?.applicationStatus === "running"}
|
||||||
className="flex items-center gap-1.5"
|
className="flex items-center gap-1.5 group focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
>
|
>
|
||||||
Rebuild
|
|
||||||
<Hammer className="size-4" />
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<HelpCircle className="size-4 text-muted-foreground hover:text-foreground transition-colors cursor-pointer" />
|
<div className="flex items-center">
|
||||||
|
<Hammer className="size-4 mr-1" />
|
||||||
|
Rebuild
|
||||||
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipPrimitive.Portal>
|
<TooltipPrimitive.Portal>
|
||||||
<TooltipContent sideOffset={5} className="z-[60]">
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
@@ -180,13 +198,14 @@ export const ShowGeneralApplication = ({ applicationId }: Props) => {
|
|||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
isLoading={isStarting}
|
isLoading={isStarting}
|
||||||
className="flex items-center gap-1.5"
|
className="flex items-center gap-1.5 group focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
>
|
>
|
||||||
Start
|
|
||||||
<CheckCircle2 className="size-4" />
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<HelpCircle className="size-4 text-muted-foreground hover:text-foreground transition-colors cursor-pointer" />
|
<div className="flex items-center">
|
||||||
|
<CheckCircle2 className="size-4 mr-1" />
|
||||||
|
Start
|
||||||
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipPrimitive.Portal>
|
<TooltipPrimitive.Portal>
|
||||||
<TooltipContent sideOffset={5} className="z-[60]">
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
@@ -219,13 +238,14 @@ export const ShowGeneralApplication = ({ applicationId }: Props) => {
|
|||||||
<Button
|
<Button
|
||||||
variant="destructive"
|
variant="destructive"
|
||||||
isLoading={isStopping}
|
isLoading={isStopping}
|
||||||
className="flex items-center gap-1.5"
|
className="flex items-center gap-1.5 group focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
>
|
>
|
||||||
Stop
|
|
||||||
<Ban className="size-4" />
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<HelpCircle className="size-4 text-muted-foreground hover:text-foreground transition-colors cursor-pointer" />
|
<div className="flex items-center">
|
||||||
|
<Ban className="size-4 mr-1" />
|
||||||
|
Stop
|
||||||
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipPrimitive.Portal>
|
<TooltipPrimitive.Portal>
|
||||||
<TooltipContent sideOffset={5} className="z-[60]">
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
@@ -241,15 +261,18 @@ export const ShowGeneralApplication = ({ applicationId }: Props) => {
|
|||||||
appName={data?.appName || ""}
|
appName={data?.appName || ""}
|
||||||
serverId={data?.serverId || ""}
|
serverId={data?.serverId || ""}
|
||||||
>
|
>
|
||||||
<Button variant="outline">
|
<Button
|
||||||
<Terminal />
|
variant="outline"
|
||||||
|
className="flex items-center gap-1.5 focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
|
>
|
||||||
|
<Terminal className="size-4 mr-1" />
|
||||||
Open Terminal
|
Open Terminal
|
||||||
</Button>
|
</Button>
|
||||||
</DockerTerminalModal>
|
</DockerTerminalModal>
|
||||||
<div className="flex flex-row items-center gap-2 rounded-md px-4 py-2 border">
|
<div className="flex flex-row items-center gap-2 rounded-md px-4 py-2 border">
|
||||||
<span className="text-sm font-medium">Autodeploy</span>
|
<span className="text-sm font-medium">Autodeploy</span>
|
||||||
<Switch
|
<Switch
|
||||||
aria-label="Toggle italic"
|
aria-label="Toggle autodeploy"
|
||||||
checked={data?.autoDeploy || false}
|
checked={data?.autoDeploy || false}
|
||||||
onCheckedChange={async (enabled) => {
|
onCheckedChange={async (enabled) => {
|
||||||
await update({
|
await update({
|
||||||
@@ -264,14 +287,14 @@ export const ShowGeneralApplication = ({ applicationId }: Props) => {
|
|||||||
toast.error("Error updating Auto Deploy");
|
toast.error("Error updating Auto Deploy");
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
className="flex flex-row gap-2 items-center"
|
className="flex flex-row gap-2 items-center data-[state=checked]:bg-primary"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-row items-center gap-2 rounded-md px-4 py-2 border">
|
<div className="flex flex-row items-center gap-2 rounded-md px-4 py-2 border">
|
||||||
<span className="text-sm font-medium">Clean Cache</span>
|
<span className="text-sm font-medium">Clean Cache</span>
|
||||||
<Switch
|
<Switch
|
||||||
aria-label="Toggle italic"
|
aria-label="Toggle clean cache"
|
||||||
checked={data?.cleanCache || false}
|
checked={data?.cleanCache || false}
|
||||||
onCheckedChange={async (enabled) => {
|
onCheckedChange={async (enabled) => {
|
||||||
await update({
|
await update({
|
||||||
@@ -286,7 +309,7 @@ export const ShowGeneralApplication = ({ applicationId }: Props) => {
|
|||||||
toast.error("Error updating Clean Cache");
|
toast.error("Error updating Clean Cache");
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
className="flex flex-row gap-2 items-center"
|
className="flex flex-row gap-2 items-center data-[state=checked]:bg-primary"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import {
|
|||||||
import { domainCompose } from "@/server/db/validations/domain";
|
import { domainCompose } from "@/server/db/validations/domain";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { DatabaseZap, Dices, RefreshCw } from "lucide-react";
|
import { DatabaseZap, Dices, RefreshCw } from "lucide-react";
|
||||||
|
import Link from "next/link";
|
||||||
import type z from "zod";
|
import type z from "zod";
|
||||||
|
|
||||||
type Domain = z.infer<typeof domainCompose>;
|
type Domain = z.infer<typeof domainCompose>;
|
||||||
@@ -102,6 +103,11 @@ export const AddDomainCompose = ({
|
|||||||
? api.domain.update.useMutation()
|
? api.domain.update.useMutation()
|
||||||
: api.domain.create.useMutation();
|
: api.domain.create.useMutation();
|
||||||
|
|
||||||
|
const { data: canGenerateTraefikMeDomains } =
|
||||||
|
api.domain.canGenerateTraefikMeDomains.useQuery({
|
||||||
|
serverId: compose?.serverId || "",
|
||||||
|
});
|
||||||
|
|
||||||
const form = useForm<Domain>({
|
const form = useForm<Domain>({
|
||||||
resolver: zodResolver(domainCompose),
|
resolver: zodResolver(domainCompose),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
@@ -313,6 +319,21 @@ export const AddDomainCompose = ({
|
|||||||
name="host"
|
name="host"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
|
{!canGenerateTraefikMeDomains &&
|
||||||
|
field.value.includes("traefik.me") && (
|
||||||
|
<AlertBlock type="warning">
|
||||||
|
You need to set an IP address in your{" "}
|
||||||
|
<Link
|
||||||
|
href="/dashboard/settings/server"
|
||||||
|
className="text-primary"
|
||||||
|
>
|
||||||
|
{compose?.serverId
|
||||||
|
? "Remote Servers -> Server -> Edit Server -> Update IP Address"
|
||||||
|
: "Web Server -> Server -> Update Server IP"}
|
||||||
|
</Link>{" "}
|
||||||
|
to make your traefik.me domain work.
|
||||||
|
</AlertBlock>
|
||||||
|
)}
|
||||||
<FormLabel>Host</FormLabel>
|
<FormLabel>Host</FormLabel>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<FormControl>
|
<FormControl>
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ import {
|
|||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from "@/components/ui/tooltip";
|
} from "@/components/ui/tooltip";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
import { Ban, CheckCircle2, RefreshCcw, Rocket, Terminal } from "lucide-react";
|
||||||
import { Ban, CheckCircle2, Hammer, HelpCircle, Terminal } from "lucide-react";
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { DockerTerminalModal } from "../../settings/web-server/docker-terminal-modal";
|
import { DockerTerminalModal } from "../../settings/web-server/docker-terminal-modal";
|
||||||
|
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
composeId: string;
|
composeId: string;
|
||||||
@@ -34,7 +34,7 @@ export const ComposeActions = ({ composeId }: Props) => {
|
|||||||
api.compose.stop.useMutation();
|
api.compose.stop.useMutation();
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-row gap-4 w-full flex-wrap ">
|
<div className="flex flex-row gap-4 w-full flex-wrap ">
|
||||||
<TooltipProvider delayDuration={0}>
|
<TooltipProvider delayDuration={0} disableHoverableContent={false}>
|
||||||
<DialogAction
|
<DialogAction
|
||||||
title="Deploy Compose"
|
title="Deploy Compose"
|
||||||
description="Are you sure you want to deploy this compose?"
|
description="Are you sure you want to deploy this compose?"
|
||||||
@@ -58,12 +58,14 @@ export const ComposeActions = ({ composeId }: Props) => {
|
|||||||
<Button
|
<Button
|
||||||
variant="default"
|
variant="default"
|
||||||
isLoading={data?.composeStatus === "running"}
|
isLoading={data?.composeStatus === "running"}
|
||||||
className="flex items-center gap-1.5"
|
className="flex items-center gap-1.5 group focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
>
|
>
|
||||||
Deploy
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<HelpCircle className="size-4 text-muted-foreground hover:text-foreground transition-colors cursor-pointer" />
|
<div className="flex items-center">
|
||||||
|
<Rocket className="size-4 mr-1" />
|
||||||
|
Deploy
|
||||||
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipPrimitive.Portal>
|
<TooltipPrimitive.Portal>
|
||||||
<TooltipContent sideOffset={5} className="z-[60]">
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
@@ -74,36 +76,37 @@ export const ComposeActions = ({ composeId }: Props) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</DialogAction>
|
</DialogAction>
|
||||||
<DialogAction
|
<DialogAction
|
||||||
title="Rebuild Compose"
|
title="Reload Compose"
|
||||||
description="Are you sure you want to rebuild this compose?"
|
description="Are you sure you want to reload this compose?"
|
||||||
type="default"
|
type="default"
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
await redeploy({
|
await redeploy({
|
||||||
composeId: composeId,
|
composeId: composeId,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
toast.success("Compose rebuilt successfully");
|
toast.success("Compose reloaded successfully");
|
||||||
refetch();
|
refetch();
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
toast.error("Error rebuilding compose");
|
toast.error("Error reloading compose");
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
isLoading={data?.composeStatus === "running"}
|
isLoading={data?.composeStatus === "running"}
|
||||||
className="flex items-center gap-1.5"
|
className="flex items-center gap-1.5 group focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
>
|
>
|
||||||
Rebuild
|
|
||||||
<Hammer className="size-4" />
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<HelpCircle className="size-4 text-muted-foreground hover:text-foreground transition-colors cursor-pointer" />
|
<div className="flex items-center">
|
||||||
|
<RefreshCcw className="size-4 mr-1" />
|
||||||
|
Reload
|
||||||
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipPrimitive.Portal>
|
<TooltipPrimitive.Portal>
|
||||||
<TooltipContent sideOffset={5} className="z-[60]">
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
<p>Only rebuilds the compose without downloading new code</p>
|
<p>Reload the compose without rebuilding it</p>
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</TooltipPrimitive.Portal>
|
</TooltipPrimitive.Portal>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
@@ -131,13 +134,14 @@ export const ComposeActions = ({ composeId }: Props) => {
|
|||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
isLoading={isStarting}
|
isLoading={isStarting}
|
||||||
className="flex items-center gap-1.5"
|
className="flex items-center gap-1.5 group focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
>
|
>
|
||||||
Start
|
|
||||||
<CheckCircle2 className="size-4" />
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<HelpCircle className="size-4 text-muted-foreground hover:text-foreground transition-colors cursor-pointer" />
|
<div className="flex items-center">
|
||||||
|
<CheckCircle2 className="size-4 mr-1" />
|
||||||
|
Start
|
||||||
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipPrimitive.Portal>
|
<TooltipPrimitive.Portal>
|
||||||
<TooltipContent sideOffset={5} className="z-[60]">
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
@@ -169,13 +173,14 @@ export const ComposeActions = ({ composeId }: Props) => {
|
|||||||
<Button
|
<Button
|
||||||
variant="destructive"
|
variant="destructive"
|
||||||
isLoading={isStopping}
|
isLoading={isStopping}
|
||||||
className="flex items-center gap-1.5"
|
className="flex items-center gap-1.5 group focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
>
|
>
|
||||||
Stop
|
|
||||||
<Ban className="size-4" />
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<HelpCircle className="size-4 text-muted-foreground hover:text-foreground transition-colors cursor-pointer" />
|
<div className="flex items-center">
|
||||||
|
<Ban className="size-4 mr-1" />
|
||||||
|
Stop
|
||||||
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipPrimitive.Portal>
|
<TooltipPrimitive.Portal>
|
||||||
<TooltipContent sideOffset={5} className="z-[60]">
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
@@ -191,15 +196,18 @@ export const ComposeActions = ({ composeId }: Props) => {
|
|||||||
appName={data?.appName || ""}
|
appName={data?.appName || ""}
|
||||||
serverId={data?.serverId || ""}
|
serverId={data?.serverId || ""}
|
||||||
>
|
>
|
||||||
<Button variant="outline">
|
<Button
|
||||||
<Terminal />
|
variant="outline"
|
||||||
|
className="flex items-center gap-1.5 focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
|
>
|
||||||
|
<Terminal className="size-4 mr-1" />
|
||||||
Open Terminal
|
Open Terminal
|
||||||
</Button>
|
</Button>
|
||||||
</DockerTerminalModal>
|
</DockerTerminalModal>
|
||||||
<div className="flex flex-row items-center gap-2 rounded-md px-4 py-2 border">
|
<div className="flex flex-row items-center gap-2 rounded-md px-4 py-2 border">
|
||||||
<span className="text-sm font-medium">Autodeploy</span>
|
<span className="text-sm font-medium">Autodeploy</span>
|
||||||
<Switch
|
<Switch
|
||||||
aria-label="Toggle italic"
|
aria-label="Toggle autodeploy"
|
||||||
checked={data?.autoDeploy || false}
|
checked={data?.autoDeploy || false}
|
||||||
onCheckedChange={async (enabled) => {
|
onCheckedChange={async (enabled) => {
|
||||||
await update({
|
await update({
|
||||||
@@ -214,7 +222,7 @@ export const ComposeActions = ({ composeId }: Props) => {
|
|||||||
toast.error("Error updating Auto Deploy");
|
toast.error("Error updating Auto Deploy");
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
className="flex flex-row gap-2 items-center"
|
className="flex flex-row gap-2 items-center data-[state=checked]:bg-primary"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,375 @@
|
|||||||
|
import { DrawerLogs } from "@/components/shared/drawer-logs";
|
||||||
|
import { Badge } from "@/components/ui/badge";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Command,
|
||||||
|
CommandEmpty,
|
||||||
|
CommandGroup,
|
||||||
|
CommandInput,
|
||||||
|
CommandItem,
|
||||||
|
} from "@/components/ui/command";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
import {
|
||||||
|
Form,
|
||||||
|
FormControl,
|
||||||
|
FormField,
|
||||||
|
FormItem,
|
||||||
|
FormLabel,
|
||||||
|
FormMessage,
|
||||||
|
} from "@/components/ui/form";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import {
|
||||||
|
Popover,
|
||||||
|
PopoverContent,
|
||||||
|
PopoverTrigger,
|
||||||
|
} from "@/components/ui/popover";
|
||||||
|
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import { api } from "@/utils/api";
|
||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import copy from "copy-to-clipboard";
|
||||||
|
import { debounce } from "lodash";
|
||||||
|
import { CheckIcon, ChevronsUpDown, Copy, RotateCcw } from "lucide-react";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
import { z } from "zod";
|
||||||
|
import type { ServiceType } from "../../application/advanced/show-resources";
|
||||||
|
import { type LogLine, parseLogs } from "../../docker/logs/utils";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
databaseId: string;
|
||||||
|
databaseType: Exclude<ServiceType, "application" | "redis">;
|
||||||
|
serverId: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const RestoreBackupSchema = z.object({
|
||||||
|
destinationId: z
|
||||||
|
.string({
|
||||||
|
required_error: "Please select a destination",
|
||||||
|
})
|
||||||
|
.min(1, {
|
||||||
|
message: "Destination is required",
|
||||||
|
}),
|
||||||
|
backupFile: z
|
||||||
|
.string({
|
||||||
|
required_error: "Please select a backup file",
|
||||||
|
})
|
||||||
|
.min(1, {
|
||||||
|
message: "Backup file is required",
|
||||||
|
}),
|
||||||
|
databaseName: z
|
||||||
|
.string({
|
||||||
|
required_error: "Please enter a database name",
|
||||||
|
})
|
||||||
|
.min(1, {
|
||||||
|
message: "Database name is required",
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
type RestoreBackup = z.infer<typeof RestoreBackupSchema>;
|
||||||
|
|
||||||
|
export const RestoreBackup = ({
|
||||||
|
databaseId,
|
||||||
|
databaseType,
|
||||||
|
serverId,
|
||||||
|
}: Props) => {
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
const [search, setSearch] = useState("");
|
||||||
|
|
||||||
|
const { data: destinations = [] } = api.destination.all.useQuery();
|
||||||
|
|
||||||
|
const form = useForm<RestoreBackup>({
|
||||||
|
defaultValues: {
|
||||||
|
destinationId: "",
|
||||||
|
backupFile: "",
|
||||||
|
databaseName: "",
|
||||||
|
},
|
||||||
|
resolver: zodResolver(RestoreBackupSchema),
|
||||||
|
});
|
||||||
|
|
||||||
|
const destionationId = form.watch("destinationId");
|
||||||
|
|
||||||
|
const debouncedSetSearch = debounce((value: string) => {
|
||||||
|
setSearch(value);
|
||||||
|
}, 300);
|
||||||
|
|
||||||
|
const { data: files = [], isLoading } = api.backup.listBackupFiles.useQuery(
|
||||||
|
{
|
||||||
|
destinationId: destionationId,
|
||||||
|
search,
|
||||||
|
serverId: serverId ?? "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
enabled: isOpen && !!destionationId,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
|
||||||
|
const [filteredLogs, setFilteredLogs] = useState<LogLine[]>([]);
|
||||||
|
const [isDeploying, setIsDeploying] = useState(false);
|
||||||
|
|
||||||
|
// const { mutateAsync: restore, isLoading: isRestoring } =
|
||||||
|
// api.backup.restoreBackup.useMutation();
|
||||||
|
|
||||||
|
api.backup.restoreBackupWithLogs.useSubscription(
|
||||||
|
{
|
||||||
|
databaseId,
|
||||||
|
databaseType,
|
||||||
|
databaseName: form.watch("databaseName"),
|
||||||
|
backupFile: form.watch("backupFile"),
|
||||||
|
destinationId: form.watch("destinationId"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
enabled: isDeploying,
|
||||||
|
onData(log) {
|
||||||
|
if (!isDrawerOpen) {
|
||||||
|
setIsDrawerOpen(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (log === "Restore completed successfully!") {
|
||||||
|
setIsDeploying(false);
|
||||||
|
}
|
||||||
|
const parsedLogs = parseLogs(log);
|
||||||
|
setFilteredLogs((prev) => [...prev, ...parsedLogs]);
|
||||||
|
},
|
||||||
|
onError(error) {
|
||||||
|
console.error("Restore logs error:", error);
|
||||||
|
setIsDeploying(false);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const onSubmit = async (_data: RestoreBackup) => {
|
||||||
|
setIsDeploying(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
||||||
|
<DialogTrigger asChild>
|
||||||
|
<Button variant="outline">
|
||||||
|
<RotateCcw className="mr-2 size-4" />
|
||||||
|
Restore Backup
|
||||||
|
</Button>
|
||||||
|
</DialogTrigger>
|
||||||
|
<DialogContent className="sm:max-w-lg">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle className="flex items-center">
|
||||||
|
<RotateCcw className="mr-2 size-4" />
|
||||||
|
Restore Backup
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
Select a destination and search for backup files
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
|
||||||
|
<Form {...form}>
|
||||||
|
<form
|
||||||
|
id="hook-form-restore-backup"
|
||||||
|
onSubmit={form.handleSubmit(onSubmit)}
|
||||||
|
className="grid w-full gap-4"
|
||||||
|
>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="destinationId"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem className="">
|
||||||
|
<FormLabel>Destination</FormLabel>
|
||||||
|
<Popover>
|
||||||
|
<PopoverTrigger asChild>
|
||||||
|
<FormControl>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
className={cn(
|
||||||
|
"w-full justify-between !bg-input",
|
||||||
|
!field.value && "text-muted-foreground",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{field.value
|
||||||
|
? destinations.find(
|
||||||
|
(d) => d.destinationId === field.value,
|
||||||
|
)?.name
|
||||||
|
: "Select Destination"}
|
||||||
|
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||||
|
</Button>
|
||||||
|
</FormControl>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent className="p-0" align="start">
|
||||||
|
<Command>
|
||||||
|
<CommandInput
|
||||||
|
placeholder="Search destinations..."
|
||||||
|
className="h-9"
|
||||||
|
/>
|
||||||
|
<CommandEmpty>No destinations found.</CommandEmpty>
|
||||||
|
<ScrollArea className="h-64">
|
||||||
|
<CommandGroup>
|
||||||
|
{destinations.map((destination) => (
|
||||||
|
<CommandItem
|
||||||
|
value={destination.destinationId}
|
||||||
|
key={destination.destinationId}
|
||||||
|
onSelect={() => {
|
||||||
|
form.setValue(
|
||||||
|
"destinationId",
|
||||||
|
destination.destinationId,
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{destination.name}
|
||||||
|
<CheckIcon
|
||||||
|
className={cn(
|
||||||
|
"ml-auto h-4 w-4",
|
||||||
|
destination.destinationId === field.value
|
||||||
|
? "opacity-100"
|
||||||
|
: "opacity-0",
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</CommandItem>
|
||||||
|
))}
|
||||||
|
</CommandGroup>
|
||||||
|
</ScrollArea>
|
||||||
|
</Command>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="backupFile"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem className="">
|
||||||
|
<FormLabel className="flex items-center justify-between">
|
||||||
|
Search Backup Files
|
||||||
|
{field.value && (
|
||||||
|
<Badge variant="outline">
|
||||||
|
{field.value}
|
||||||
|
<Copy
|
||||||
|
className="ml-2 size-4 cursor-pointer"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
copy(field.value);
|
||||||
|
toast.success("Backup file copied to clipboard");
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
|
</FormLabel>
|
||||||
|
<Popover>
|
||||||
|
<PopoverTrigger asChild>
|
||||||
|
<FormControl>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
className={cn(
|
||||||
|
"w-full justify-between !bg-input",
|
||||||
|
!field.value && "text-muted-foreground",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{field.value || "Search and select a backup file"}
|
||||||
|
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||||
|
</Button>
|
||||||
|
</FormControl>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent className="p-0" align="start">
|
||||||
|
<Command>
|
||||||
|
<CommandInput
|
||||||
|
placeholder="Search backup files..."
|
||||||
|
onValueChange={debouncedSetSearch}
|
||||||
|
className="h-9"
|
||||||
|
/>
|
||||||
|
{isLoading ? (
|
||||||
|
<div className="py-6 text-center text-sm">
|
||||||
|
Loading backup files...
|
||||||
|
</div>
|
||||||
|
) : files.length === 0 && search ? (
|
||||||
|
<div className="py-6 text-center text-sm text-muted-foreground">
|
||||||
|
No backup files found for "{search}"
|
||||||
|
</div>
|
||||||
|
) : files.length === 0 ? (
|
||||||
|
<div className="py-6 text-center text-sm text-muted-foreground">
|
||||||
|
No backup files available
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<ScrollArea className="h-64">
|
||||||
|
<CommandGroup>
|
||||||
|
{files.map((file) => (
|
||||||
|
<CommandItem
|
||||||
|
value={file}
|
||||||
|
key={file}
|
||||||
|
onSelect={() => {
|
||||||
|
form.setValue("backupFile", file);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="flex w-full justify-between">
|
||||||
|
<span>{file}</span>
|
||||||
|
</div>
|
||||||
|
<CheckIcon
|
||||||
|
className={cn(
|
||||||
|
"ml-auto h-4 w-4",
|
||||||
|
file === field.value
|
||||||
|
? "opacity-100"
|
||||||
|
: "opacity-0",
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</CommandItem>
|
||||||
|
))}
|
||||||
|
</CommandGroup>
|
||||||
|
</ScrollArea>
|
||||||
|
)}
|
||||||
|
</Command>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="databaseName"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem className="">
|
||||||
|
<FormLabel>Database Name</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input {...field} placeholder="Enter database name" />
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<DialogFooter>
|
||||||
|
<Button
|
||||||
|
isLoading={isDeploying}
|
||||||
|
form="hook-form-restore-backup"
|
||||||
|
type="submit"
|
||||||
|
disabled={!form.watch("backupFile")}
|
||||||
|
>
|
||||||
|
Restore
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</form>
|
||||||
|
</Form>
|
||||||
|
|
||||||
|
<DrawerLogs
|
||||||
|
isOpen={isDrawerOpen}
|
||||||
|
onClose={() => {
|
||||||
|
setIsDrawerOpen(false);
|
||||||
|
setFilteredLogs([]);
|
||||||
|
setIsDeploying(false);
|
||||||
|
// refetch();
|
||||||
|
}}
|
||||||
|
filteredLogs={filteredLogs}
|
||||||
|
/>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -20,6 +20,7 @@ import { useState } from "react";
|
|||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import type { ServiceType } from "../../application/advanced/show-resources";
|
import type { ServiceType } from "../../application/advanced/show-resources";
|
||||||
import { AddBackup } from "./add-backup";
|
import { AddBackup } from "./add-backup";
|
||||||
|
import { RestoreBackup } from "./restore-backup";
|
||||||
import { UpdateBackup } from "./update-backup";
|
import { UpdateBackup } from "./update-backup";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -71,7 +72,14 @@ export const ShowBackups = ({ id, type }: Props) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{postgres && postgres?.backups?.length > 0 && (
|
{postgres && postgres?.backups?.length > 0 && (
|
||||||
<AddBackup databaseId={id} databaseType={type} refetch={refetch} />
|
<div className="flex flex-col lg:flex-row gap-4 w-full lg:w-auto">
|
||||||
|
<AddBackup databaseId={id} databaseType={type} refetch={refetch} />
|
||||||
|
<RestoreBackup
|
||||||
|
databaseId={id}
|
||||||
|
databaseType={type}
|
||||||
|
serverId={postgres.serverId}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="flex flex-col gap-4">
|
<CardContent className="flex flex-col gap-4">
|
||||||
@@ -98,11 +106,18 @@ export const ShowBackups = ({ id, type }: Props) => {
|
|||||||
<span className="text-base text-muted-foreground">
|
<span className="text-base text-muted-foreground">
|
||||||
No backups configured
|
No backups configured
|
||||||
</span>
|
</span>
|
||||||
<AddBackup
|
<div className="flex flex-col sm:flex-row gap-4 w-full sm:w-auto">
|
||||||
databaseId={id}
|
<AddBackup
|
||||||
databaseType={type}
|
databaseId={id}
|
||||||
refetch={refetch}
|
databaseType={type}
|
||||||
/>
|
refetch={refetch}
|
||||||
|
/>
|
||||||
|
<RestoreBackup
|
||||||
|
databaseId={id}
|
||||||
|
databaseType={type}
|
||||||
|
serverId={postgres.serverId}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex flex-col pt-2">
|
<div className="flex flex-col pt-2">
|
||||||
@@ -183,6 +198,7 @@ export const ShowBackups = ({ id, type }: Props) => {
|
|||||||
<TooltipContent>Run Manual Backup</TooltipContent>
|
<TooltipContent>Run Manual Backup</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
|
|
||||||
<UpdateBackup
|
<UpdateBackup
|
||||||
backupId={backup.backupId}
|
backupId={backup.backupId}
|
||||||
refetch={refetch}
|
refetch={refetch}
|
||||||
|
|||||||
@@ -119,7 +119,6 @@ export const DockerLogsId: React.FC<Props> = ({
|
|||||||
const wsUrl = `${protocol}//${
|
const wsUrl = `${protocol}//${
|
||||||
window.location.host
|
window.location.host
|
||||||
}/docker-container-logs?${params.toString()}`;
|
}/docker-container-logs?${params.toString()}`;
|
||||||
console.log("Connecting to WebSocket:", wsUrl);
|
|
||||||
const ws = new WebSocket(wsUrl);
|
const ws = new WebSocket(wsUrl);
|
||||||
|
|
||||||
const resetNoDataTimeout = () => {
|
const resetNoDataTimeout = () => {
|
||||||
@@ -136,7 +135,6 @@ export const DockerLogsId: React.FC<Props> = ({
|
|||||||
ws.close();
|
ws.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log("WebSocket connected");
|
|
||||||
resetNoDataTimeout();
|
resetNoDataTimeout();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -111,7 +111,10 @@ export const ShowExternalMariadbCredentials = ({ mariadbId }: Props) => {
|
|||||||
{!getIp && (
|
{!getIp && (
|
||||||
<AlertBlock type="warning">
|
<AlertBlock type="warning">
|
||||||
You need to set an IP address in your{" "}
|
You need to set an IP address in your{" "}
|
||||||
<Link href="/dashboard/settings" className="text-primary">
|
<Link
|
||||||
|
href="/dashboard/settings/server"
|
||||||
|
className="text-primary"
|
||||||
|
>
|
||||||
{data?.serverId
|
{data?.serverId
|
||||||
? "Remote Servers -> Server -> Edit Server -> Update IP Address"
|
? "Remote Servers -> Server -> Edit Server -> Update IP Address"
|
||||||
: "Web Server -> Server -> Update Server IP"}
|
: "Web Server -> Server -> Update Server IP"}
|
||||||
|
|||||||
@@ -10,13 +10,7 @@ import {
|
|||||||
} from "@/components/ui/tooltip";
|
} from "@/components/ui/tooltip";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
||||||
import {
|
import { Ban, CheckCircle2, RefreshCcw, Rocket, Terminal } from "lucide-react";
|
||||||
Ban,
|
|
||||||
CheckCircle2,
|
|
||||||
HelpCircle,
|
|
||||||
RefreshCcw,
|
|
||||||
Terminal,
|
|
||||||
} from "lucide-react";
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { type LogLine, parseLogs } from "../../docker/logs/utils";
|
import { type LogLine, parseLogs } from "../../docker/logs/utils";
|
||||||
@@ -92,12 +86,14 @@ export const ShowGeneralMariadb = ({ mariadbId }: Props) => {
|
|||||||
<Button
|
<Button
|
||||||
variant="default"
|
variant="default"
|
||||||
isLoading={data?.applicationStatus === "running"}
|
isLoading={data?.applicationStatus === "running"}
|
||||||
className="flex items-center gap-1.5"
|
className="flex items-center gap-1.5 focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
>
|
>
|
||||||
Deploy
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<HelpCircle className="size-4 text-muted-foreground hover:text-foreground transition-colors cursor-pointer" />
|
<div className="flex items-center">
|
||||||
|
<Rocket className="size-4 mr-1" />
|
||||||
|
Deploy
|
||||||
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipPrimitive.Portal>
|
<TooltipPrimitive.Portal>
|
||||||
<TooltipContent sideOffset={5} className="z-[60]">
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
@@ -107,6 +103,8 @@ export const ShowGeneralMariadb = ({ mariadbId }: Props) => {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Button>
|
</Button>
|
||||||
</DialogAction>
|
</DialogAction>
|
||||||
|
</TooltipProvider>
|
||||||
|
<TooltipProvider delayDuration={0}>
|
||||||
<DialogAction
|
<DialogAction
|
||||||
title="Reload Mariadb"
|
title="Reload Mariadb"
|
||||||
description="Are you sure you want to reload this mariadb?"
|
description="Are you sure you want to reload this mariadb?"
|
||||||
@@ -128,13 +126,14 @@ export const ShowGeneralMariadb = ({ mariadbId }: Props) => {
|
|||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
isLoading={isReloading}
|
isLoading={isReloading}
|
||||||
className="flex items-center gap-1.5"
|
className="flex items-center gap-1.5 focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
>
|
>
|
||||||
Reload
|
|
||||||
<RefreshCcw className="size-4" />
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<HelpCircle className="size-4 text-muted-foreground hover:text-foreground transition-colors cursor-pointer" />
|
<div className="flex items-center">
|
||||||
|
<RefreshCcw className="size-4 mr-1" />
|
||||||
|
Reload
|
||||||
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipPrimitive.Portal>
|
<TooltipPrimitive.Portal>
|
||||||
<TooltipContent sideOffset={5} className="z-[60]">
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
@@ -144,7 +143,9 @@ export const ShowGeneralMariadb = ({ mariadbId }: Props) => {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Button>
|
</Button>
|
||||||
</DialogAction>
|
</DialogAction>
|
||||||
{data?.applicationStatus === "idle" ? (
|
</TooltipProvider>
|
||||||
|
{data?.applicationStatus === "idle" ? (
|
||||||
|
<TooltipProvider delayDuration={0}>
|
||||||
<DialogAction
|
<DialogAction
|
||||||
title="Start Mariadb"
|
title="Start Mariadb"
|
||||||
description="Are you sure you want to start this mariadb?"
|
description="Are you sure you want to start this mariadb?"
|
||||||
@@ -165,13 +166,14 @@ export const ShowGeneralMariadb = ({ mariadbId }: Props) => {
|
|||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
isLoading={isStarting}
|
isLoading={isStarting}
|
||||||
className="flex items-center gap-1.5"
|
className="flex items-center gap-1.5 focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
>
|
>
|
||||||
Start
|
|
||||||
<CheckCircle2 className="size-4" />
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<HelpCircle className="size-4 text-muted-foreground hover:text-foreground transition-colors cursor-pointer" />
|
<div className="flex items-center">
|
||||||
|
<CheckCircle2 className="size-4 mr-1" />
|
||||||
|
Start
|
||||||
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipPrimitive.Portal>
|
<TooltipPrimitive.Portal>
|
||||||
<TooltipContent sideOffset={5} className="z-[60]">
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
@@ -184,7 +186,9 @@ export const ShowGeneralMariadb = ({ mariadbId }: Props) => {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Button>
|
</Button>
|
||||||
</DialogAction>
|
</DialogAction>
|
||||||
) : (
|
</TooltipProvider>
|
||||||
|
) : (
|
||||||
|
<TooltipProvider delayDuration={0}>
|
||||||
<DialogAction
|
<DialogAction
|
||||||
title="Stop Mariadb"
|
title="Stop Mariadb"
|
||||||
description="Are you sure you want to stop this mariadb?"
|
description="Are you sure you want to stop this mariadb?"
|
||||||
@@ -204,13 +208,14 @@ export const ShowGeneralMariadb = ({ mariadbId }: Props) => {
|
|||||||
<Button
|
<Button
|
||||||
variant="destructive"
|
variant="destructive"
|
||||||
isLoading={isStopping}
|
isLoading={isStopping}
|
||||||
className="flex items-center gap-1.5"
|
className="flex items-center gap-1.5 focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
>
|
>
|
||||||
Stop
|
|
||||||
<Ban className="size-4" />
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<HelpCircle className="size-4 text-muted-foreground hover:text-foreground transition-colors cursor-pointer" />
|
<div className="flex items-center">
|
||||||
|
<Ban className="size-4 mr-1" />
|
||||||
|
Stop
|
||||||
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipPrimitive.Portal>
|
<TooltipPrimitive.Portal>
|
||||||
<TooltipContent sideOffset={5} className="z-[60]">
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
@@ -220,15 +225,29 @@ export const ShowGeneralMariadb = ({ mariadbId }: Props) => {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Button>
|
</Button>
|
||||||
</DialogAction>
|
</DialogAction>
|
||||||
)}
|
</TooltipProvider>
|
||||||
</TooltipProvider>
|
)}
|
||||||
<DockerTerminalModal
|
<DockerTerminalModal
|
||||||
appName={data?.appName || ""}
|
appName={data?.appName || ""}
|
||||||
serverId={data?.serverId || ""}
|
serverId={data?.serverId || ""}
|
||||||
>
|
>
|
||||||
<Button variant="outline">
|
<Button
|
||||||
<Terminal />
|
variant="outline"
|
||||||
Open Terminal
|
className="flex items-center gap-1.5 focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
|
>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<div className="flex items-center">
|
||||||
|
<Terminal className="size-4 mr-1" />
|
||||||
|
Open Terminal
|
||||||
|
</div>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipPrimitive.Portal>
|
||||||
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
|
<p>Open a terminal to the MariaDB container</p>
|
||||||
|
</TooltipContent>
|
||||||
|
</TooltipPrimitive.Portal>
|
||||||
|
</Tooltip>
|
||||||
</Button>
|
</Button>
|
||||||
</DockerTerminalModal>
|
</DockerTerminalModal>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|||||||
@@ -111,7 +111,10 @@ export const ShowExternalMongoCredentials = ({ mongoId }: Props) => {
|
|||||||
{!getIp && (
|
{!getIp && (
|
||||||
<AlertBlock type="warning">
|
<AlertBlock type="warning">
|
||||||
You need to set an IP address in your{" "}
|
You need to set an IP address in your{" "}
|
||||||
<Link href="/dashboard/settings" className="text-primary">
|
<Link
|
||||||
|
href="/dashboard/settings/server"
|
||||||
|
className="text-primary"
|
||||||
|
>
|
||||||
{data?.serverId
|
{data?.serverId
|
||||||
? "Remote Servers -> Server -> Edit Server -> Update IP Address"
|
? "Remote Servers -> Server -> Edit Server -> Update IP Address"
|
||||||
: "Web Server -> Server -> Update Server IP"}
|
: "Web Server -> Server -> Update Server IP"}
|
||||||
|
|||||||
@@ -10,13 +10,7 @@ import {
|
|||||||
} from "@/components/ui/tooltip";
|
} from "@/components/ui/tooltip";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
||||||
import {
|
import { Ban, CheckCircle2, RefreshCcw, Rocket, Terminal } from "lucide-react";
|
||||||
Ban,
|
|
||||||
CheckCircle2,
|
|
||||||
HelpCircle,
|
|
||||||
RefreshCcw,
|
|
||||||
Terminal,
|
|
||||||
} from "lucide-react";
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { type LogLine, parseLogs } from "../../docker/logs/utils";
|
import { type LogLine, parseLogs } from "../../docker/logs/utils";
|
||||||
@@ -91,12 +85,14 @@ export const ShowGeneralMongo = ({ mongoId }: Props) => {
|
|||||||
<Button
|
<Button
|
||||||
variant="default"
|
variant="default"
|
||||||
isLoading={data?.applicationStatus === "running"}
|
isLoading={data?.applicationStatus === "running"}
|
||||||
className="flex items-center gap-1.5"
|
className="flex items-center gap-1.5 focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
>
|
>
|
||||||
Deploy
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<HelpCircle className="size-4 text-muted-foreground hover:text-foreground transition-colors cursor-pointer" />
|
<div className="flex items-center">
|
||||||
|
<Rocket className="size-4 mr-1" />
|
||||||
|
Deploy
|
||||||
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipPrimitive.Portal>
|
<TooltipPrimitive.Portal>
|
||||||
<TooltipContent sideOffset={5} className="z-[60]">
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
@@ -127,13 +123,14 @@ export const ShowGeneralMongo = ({ mongoId }: Props) => {
|
|||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
isLoading={isReloading}
|
isLoading={isReloading}
|
||||||
className="flex items-center gap-1.5"
|
className="flex items-center gap-1.5 focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
>
|
>
|
||||||
Reload
|
|
||||||
<RefreshCcw className="size-4" />
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<HelpCircle className="size-4 text-muted-foreground hover:text-foreground transition-colors cursor-pointer" />
|
<div className="flex items-center">
|
||||||
|
<RefreshCcw className="size-4 mr-1" />
|
||||||
|
Reload
|
||||||
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipPrimitive.Portal>
|
<TooltipPrimitive.Portal>
|
||||||
<TooltipContent sideOffset={5} className="z-[60]">
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
@@ -164,13 +161,14 @@ export const ShowGeneralMongo = ({ mongoId }: Props) => {
|
|||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
isLoading={isStarting}
|
isLoading={isStarting}
|
||||||
className="flex items-center gap-1.5"
|
className="flex items-center gap-1.5 focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
>
|
>
|
||||||
Start
|
|
||||||
<CheckCircle2 className="size-4" />
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<HelpCircle className="size-4 text-muted-foreground hover:text-foreground transition-colors cursor-pointer" />
|
<div className="flex items-center">
|
||||||
|
<CheckCircle2 className="size-4 mr-1" />
|
||||||
|
Start
|
||||||
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipPrimitive.Portal>
|
<TooltipPrimitive.Portal>
|
||||||
<TooltipContent sideOffset={5} className="z-[60]">
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
@@ -203,13 +201,14 @@ export const ShowGeneralMongo = ({ mongoId }: Props) => {
|
|||||||
<Button
|
<Button
|
||||||
variant="destructive"
|
variant="destructive"
|
||||||
isLoading={isStopping}
|
isLoading={isStopping}
|
||||||
className="flex items-center gap-1.5"
|
className="flex items-center gap-1.5 focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
>
|
>
|
||||||
Stop
|
|
||||||
<Ban className="size-4" />
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<HelpCircle className="size-4 text-muted-foreground hover:text-foreground transition-colors cursor-pointer" />
|
<div className="flex items-center">
|
||||||
|
<Ban className="size-4 mr-1" />
|
||||||
|
Stop
|
||||||
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipPrimitive.Portal>
|
<TooltipPrimitive.Portal>
|
||||||
<TooltipContent sideOffset={5} className="z-[60]">
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
@@ -225,9 +224,23 @@ export const ShowGeneralMongo = ({ mongoId }: Props) => {
|
|||||||
appName={data?.appName || ""}
|
appName={data?.appName || ""}
|
||||||
serverId={data?.serverId || ""}
|
serverId={data?.serverId || ""}
|
||||||
>
|
>
|
||||||
<Button variant="outline">
|
<Button
|
||||||
<Terminal />
|
variant="outline"
|
||||||
Open Terminal
|
className="flex items-center gap-1.5 focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
|
>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<div className="flex items-center">
|
||||||
|
<Terminal className="size-4 mr-1" />
|
||||||
|
Open Terminal
|
||||||
|
</div>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipPrimitive.Portal>
|
||||||
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
|
<p>Open a terminal to the MongoDB container</p>
|
||||||
|
</TooltipContent>
|
||||||
|
</TooltipPrimitive.Portal>
|
||||||
|
</Tooltip>
|
||||||
</Button>
|
</Button>
|
||||||
</DockerTerminalModal>
|
</DockerTerminalModal>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|||||||
@@ -111,7 +111,10 @@ export const ShowExternalMysqlCredentials = ({ mysqlId }: Props) => {
|
|||||||
{!getIp && (
|
{!getIp && (
|
||||||
<AlertBlock type="warning">
|
<AlertBlock type="warning">
|
||||||
You need to set an IP address in your{" "}
|
You need to set an IP address in your{" "}
|
||||||
<Link href="/dashboard/settings" className="text-primary">
|
<Link
|
||||||
|
href="/dashboard/settings/server"
|
||||||
|
className="text-primary"
|
||||||
|
>
|
||||||
{data?.serverId
|
{data?.serverId
|
||||||
? "Remote Servers -> Server -> Edit Server -> Update IP Address"
|
? "Remote Servers -> Server -> Edit Server -> Update IP Address"
|
||||||
: "Web Server -> Server -> Update Server IP"}
|
: "Web Server -> Server -> Update Server IP"}
|
||||||
|
|||||||
@@ -10,13 +10,7 @@ import {
|
|||||||
} from "@/components/ui/tooltip";
|
} from "@/components/ui/tooltip";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
||||||
import {
|
import { Ban, CheckCircle2, RefreshCcw, Rocket, Terminal } from "lucide-react";
|
||||||
Ban,
|
|
||||||
CheckCircle2,
|
|
||||||
HelpCircle,
|
|
||||||
RefreshCcw,
|
|
||||||
Terminal,
|
|
||||||
} from "lucide-react";
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { type LogLine, parseLogs } from "../../docker/logs/utils";
|
import { type LogLine, parseLogs } from "../../docker/logs/utils";
|
||||||
@@ -77,7 +71,7 @@ export const ShowGeneralMysql = ({ mysqlId }: Props) => {
|
|||||||
<CardContent className="flex flex-row gap-4 flex-wrap">
|
<CardContent className="flex flex-row gap-4 flex-wrap">
|
||||||
<TooltipProvider delayDuration={0}>
|
<TooltipProvider delayDuration={0}>
|
||||||
<DialogAction
|
<DialogAction
|
||||||
title="Deploy Mysql"
|
title="Deploy MySQL"
|
||||||
description="Are you sure you want to deploy this mysql?"
|
description="Are you sure you want to deploy this mysql?"
|
||||||
type="default"
|
type="default"
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
@@ -89,12 +83,14 @@ export const ShowGeneralMysql = ({ mysqlId }: Props) => {
|
|||||||
<Button
|
<Button
|
||||||
variant="default"
|
variant="default"
|
||||||
isLoading={data?.applicationStatus === "running"}
|
isLoading={data?.applicationStatus === "running"}
|
||||||
className="flex items-center gap-1.5"
|
className="flex items-center gap-1.5 focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
>
|
>
|
||||||
Deploy
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<HelpCircle className="size-4 text-muted-foreground hover:text-foreground transition-colors cursor-pointer" />
|
<div className="flex items-center">
|
||||||
|
<Rocket className="size-4 mr-1" />
|
||||||
|
Deploy
|
||||||
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipPrimitive.Portal>
|
<TooltipPrimitive.Portal>
|
||||||
<TooltipContent sideOffset={5} className="z-[60]">
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
@@ -105,7 +101,7 @@ export const ShowGeneralMysql = ({ mysqlId }: Props) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</DialogAction>
|
</DialogAction>
|
||||||
<DialogAction
|
<DialogAction
|
||||||
title="Reload Mysql"
|
title="Reload MySQL"
|
||||||
description="Are you sure you want to reload this mysql?"
|
description="Are you sure you want to reload this mysql?"
|
||||||
type="default"
|
type="default"
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
@@ -114,24 +110,25 @@ export const ShowGeneralMysql = ({ mysqlId }: Props) => {
|
|||||||
appName: data?.appName || "",
|
appName: data?.appName || "",
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
toast.success("Mysql reloaded successfully");
|
toast.success("MySQL reloaded successfully");
|
||||||
refetch();
|
refetch();
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
toast.error("Error reloading Mysql");
|
toast.error("Error reloading MySQL");
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
isLoading={isReloading}
|
isLoading={isReloading}
|
||||||
className="flex items-center gap-1.5"
|
className="flex items-center gap-1.5 focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
>
|
>
|
||||||
Reload
|
|
||||||
<RefreshCcw className="size-4" />
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<HelpCircle className="size-4 text-muted-foreground hover:text-foreground transition-colors cursor-pointer" />
|
<div className="flex items-center">
|
||||||
|
<RefreshCcw className="size-4 mr-1" />
|
||||||
|
Reload
|
||||||
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipPrimitive.Portal>
|
<TooltipPrimitive.Portal>
|
||||||
<TooltipContent sideOffset={5} className="z-[60]">
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
@@ -143,7 +140,7 @@ export const ShowGeneralMysql = ({ mysqlId }: Props) => {
|
|||||||
</DialogAction>
|
</DialogAction>
|
||||||
{data?.applicationStatus === "idle" ? (
|
{data?.applicationStatus === "idle" ? (
|
||||||
<DialogAction
|
<DialogAction
|
||||||
title="Start Mysql"
|
title="Start MySQL"
|
||||||
description="Are you sure you want to start this mysql?"
|
description="Are you sure you want to start this mysql?"
|
||||||
type="default"
|
type="default"
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
@@ -151,24 +148,25 @@ export const ShowGeneralMysql = ({ mysqlId }: Props) => {
|
|||||||
mysqlId: mysqlId,
|
mysqlId: mysqlId,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
toast.success("Mysql started successfully");
|
toast.success("MySQL started successfully");
|
||||||
refetch();
|
refetch();
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
toast.error("Error starting Mysql");
|
toast.error("Error starting MySQL");
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
isLoading={isStarting}
|
isLoading={isStarting}
|
||||||
className="flex items-center gap-1.5"
|
className="flex items-center gap-1.5 focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
>
|
>
|
||||||
Start
|
|
||||||
<CheckCircle2 className="size-4" />
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<HelpCircle className="size-4 text-muted-foreground hover:text-foreground transition-colors cursor-pointer" />
|
<div className="flex items-center">
|
||||||
|
<CheckCircle2 className="size-4 mr-1" />
|
||||||
|
Start
|
||||||
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipPrimitive.Portal>
|
<TooltipPrimitive.Portal>
|
||||||
<TooltipContent sideOffset={5} className="z-[60]">
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
@@ -183,31 +181,32 @@ export const ShowGeneralMysql = ({ mysqlId }: Props) => {
|
|||||||
</DialogAction>
|
</DialogAction>
|
||||||
) : (
|
) : (
|
||||||
<DialogAction
|
<DialogAction
|
||||||
title="Stop Mysql"
|
title="Stop MySQL"
|
||||||
description="Are you sure you want to stop this mysql?"
|
description="Are you sure you want to stop this mysql?"
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
await stop({
|
await stop({
|
||||||
mysqlId: mysqlId,
|
mysqlId: mysqlId,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
toast.success("Mysql stopped successfully");
|
toast.success("MySQL stopped successfully");
|
||||||
refetch();
|
refetch();
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
toast.error("Error stopping Mysql");
|
toast.error("Error stopping MySQL");
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
variant="destructive"
|
variant="destructive"
|
||||||
isLoading={isStopping}
|
isLoading={isStopping}
|
||||||
className="flex items-center gap-1.5"
|
className="flex items-center gap-1.5 focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
>
|
>
|
||||||
Stop
|
|
||||||
<Ban className="size-4" />
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<HelpCircle className="size-4 text-muted-foreground hover:text-foreground transition-colors cursor-pointer" />
|
<div className="flex items-center">
|
||||||
|
<Ban className="size-4 mr-1" />
|
||||||
|
Stop
|
||||||
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipPrimitive.Portal>
|
<TooltipPrimitive.Portal>
|
||||||
<TooltipContent sideOffset={5} className="z-[60]">
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
@@ -223,9 +222,23 @@ export const ShowGeneralMysql = ({ mysqlId }: Props) => {
|
|||||||
appName={data?.appName || ""}
|
appName={data?.appName || ""}
|
||||||
serverId={data?.serverId || ""}
|
serverId={data?.serverId || ""}
|
||||||
>
|
>
|
||||||
<Button variant="outline">
|
<Button
|
||||||
<Terminal />
|
variant="outline"
|
||||||
Open Terminal
|
className="flex items-center gap-1.5 focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
|
>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<div className="flex items-center">
|
||||||
|
<Terminal className="size-4 mr-1" />
|
||||||
|
Open Terminal
|
||||||
|
</div>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipPrimitive.Portal>
|
||||||
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
|
<p>Open a terminal to the MySQL container</p>
|
||||||
|
</TooltipContent>
|
||||||
|
</TooltipPrimitive.Portal>
|
||||||
|
</Tooltip>
|
||||||
</Button>
|
</Button>
|
||||||
</DockerTerminalModal>
|
</DockerTerminalModal>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|||||||
@@ -113,7 +113,10 @@ export const ShowExternalPostgresCredentials = ({ postgresId }: Props) => {
|
|||||||
{!getIp && (
|
{!getIp && (
|
||||||
<AlertBlock type="warning">
|
<AlertBlock type="warning">
|
||||||
You need to set an IP address in your{" "}
|
You need to set an IP address in your{" "}
|
||||||
<Link href="/dashboard/settings" className="text-primary">
|
<Link
|
||||||
|
href="/dashboard/settings/server"
|
||||||
|
className="text-primary"
|
||||||
|
>
|
||||||
{data?.serverId
|
{data?.serverId
|
||||||
? "Remote Servers -> Server -> Edit Server -> Update IP Address"
|
? "Remote Servers -> Server -> Edit Server -> Update IP Address"
|
||||||
: "Web Server -> Server -> Update Server IP"}
|
: "Web Server -> Server -> Update Server IP"}
|
||||||
|
|||||||
@@ -10,13 +10,7 @@ import {
|
|||||||
} from "@/components/ui/tooltip";
|
} from "@/components/ui/tooltip";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
||||||
import {
|
import { Ban, CheckCircle2, RefreshCcw, Rocket, Terminal } from "lucide-react";
|
||||||
Ban,
|
|
||||||
CheckCircle2,
|
|
||||||
HelpCircle,
|
|
||||||
RefreshCcw,
|
|
||||||
Terminal,
|
|
||||||
} from "lucide-react";
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { type LogLine, parseLogs } from "../../docker/logs/utils";
|
import { type LogLine, parseLogs } from "../../docker/logs/utils";
|
||||||
@@ -78,9 +72,9 @@ export const ShowGeneralPostgres = ({ postgresId }: Props) => {
|
|||||||
<CardTitle className="text-xl">Deploy Settings</CardTitle>
|
<CardTitle className="text-xl">Deploy Settings</CardTitle>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="flex flex-row gap-4 flex-wrap">
|
<CardContent className="flex flex-row gap-4 flex-wrap">
|
||||||
<TooltipProvider delayDuration={0}>
|
<TooltipProvider disableHoverableContent={false}>
|
||||||
<DialogAction
|
<DialogAction
|
||||||
title="Deploy Postgres"
|
title="Deploy PostgreSQL"
|
||||||
description="Are you sure you want to deploy this postgres?"
|
description="Are you sure you want to deploy this postgres?"
|
||||||
type="default"
|
type="default"
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
@@ -92,12 +86,14 @@ export const ShowGeneralPostgres = ({ postgresId }: Props) => {
|
|||||||
<Button
|
<Button
|
||||||
variant="default"
|
variant="default"
|
||||||
isLoading={data?.applicationStatus === "running"}
|
isLoading={data?.applicationStatus === "running"}
|
||||||
className="flex items-center gap-1.5"
|
className="flex items-center gap-1.5 focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
>
|
>
|
||||||
Deploy
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<HelpCircle className="size-4 text-muted-foreground hover:text-foreground transition-colors cursor-pointer" />
|
<div className="flex items-center">
|
||||||
|
<Rocket className="size-4 mr-1" />
|
||||||
|
Deploy
|
||||||
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipPrimitive.Portal>
|
<TooltipPrimitive.Portal>
|
||||||
<TooltipContent sideOffset={5} className="z-[60]">
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
@@ -108,7 +104,7 @@ export const ShowGeneralPostgres = ({ postgresId }: Props) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</DialogAction>
|
</DialogAction>
|
||||||
<DialogAction
|
<DialogAction
|
||||||
title="Reload Postgres"
|
title="Reload PostgreSQL"
|
||||||
description="Are you sure you want to reload this postgres?"
|
description="Are you sure you want to reload this postgres?"
|
||||||
type="default"
|
type="default"
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
@@ -117,24 +113,25 @@ export const ShowGeneralPostgres = ({ postgresId }: Props) => {
|
|||||||
appName: data?.appName || "",
|
appName: data?.appName || "",
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
toast.success("Postgres reloaded successfully");
|
toast.success("PostgreSQL reloaded successfully");
|
||||||
refetch();
|
refetch();
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
toast.error("Error reloading Postgres");
|
toast.error("Error reloading PostgreSQL");
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
isLoading={isReloading}
|
isLoading={isReloading}
|
||||||
className="flex items-center gap-1.5"
|
className="flex items-center gap-1.5 focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
>
|
>
|
||||||
Reload
|
|
||||||
<RefreshCcw className="size-4" />
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<HelpCircle className="size-4 text-muted-foreground hover:text-foreground transition-colors cursor-pointer" />
|
<div className="flex items-center">
|
||||||
|
<RefreshCcw className="size-4 mr-1" />
|
||||||
|
Reload
|
||||||
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipPrimitive.Portal>
|
<TooltipPrimitive.Portal>
|
||||||
<TooltipContent sideOffset={5} className="z-[60]">
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
@@ -146,7 +143,7 @@ export const ShowGeneralPostgres = ({ postgresId }: Props) => {
|
|||||||
</DialogAction>
|
</DialogAction>
|
||||||
{data?.applicationStatus === "idle" ? (
|
{data?.applicationStatus === "idle" ? (
|
||||||
<DialogAction
|
<DialogAction
|
||||||
title="Start Postgres"
|
title="Start PostgreSQL"
|
||||||
description="Are you sure you want to start this postgres?"
|
description="Are you sure you want to start this postgres?"
|
||||||
type="default"
|
type="default"
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
@@ -154,24 +151,25 @@ export const ShowGeneralPostgres = ({ postgresId }: Props) => {
|
|||||||
postgresId: postgresId,
|
postgresId: postgresId,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
toast.success("Postgres started successfully");
|
toast.success("PostgreSQL started successfully");
|
||||||
refetch();
|
refetch();
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
toast.error("Error starting Postgres");
|
toast.error("Error starting PostgreSQL");
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
isLoading={isStarting}
|
isLoading={isStarting}
|
||||||
className="flex items-center gap-1.5"
|
className="flex items-center gap-1.5 focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
>
|
>
|
||||||
Start
|
|
||||||
<CheckCircle2 className="size-4" />
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<HelpCircle className="size-4 text-muted-foreground hover:text-foreground transition-colors cursor-pointer" />
|
<div className="flex items-center">
|
||||||
|
<CheckCircle2 className="size-4 mr-1" />
|
||||||
|
Start
|
||||||
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipPrimitive.Portal>
|
<TooltipPrimitive.Portal>
|
||||||
<TooltipContent sideOffset={5} className="z-[60]">
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
@@ -186,31 +184,32 @@ export const ShowGeneralPostgres = ({ postgresId }: Props) => {
|
|||||||
</DialogAction>
|
</DialogAction>
|
||||||
) : (
|
) : (
|
||||||
<DialogAction
|
<DialogAction
|
||||||
title="Stop Postgres"
|
title="Stop PostgreSQL"
|
||||||
description="Are you sure you want to stop this postgres?"
|
description="Are you sure you want to stop this postgres?"
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
await stop({
|
await stop({
|
||||||
postgresId: postgresId,
|
postgresId: postgresId,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
toast.success("Postgres stopped successfully");
|
toast.success("PostgreSQL stopped successfully");
|
||||||
refetch();
|
refetch();
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
toast.error("Error stopping Postgres");
|
toast.error("Error stopping PostgreSQL");
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
variant="destructive"
|
variant="destructive"
|
||||||
isLoading={isStopping}
|
isLoading={isStopping}
|
||||||
className="flex items-center gap-1.5"
|
className="flex items-center gap-1.5 focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
>
|
>
|
||||||
Stop
|
|
||||||
<Ban className="size-4" />
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<HelpCircle className="size-4 text-muted-foreground hover:text-foreground transition-colors cursor-pointer" />
|
<div className="flex items-center">
|
||||||
|
<Ban className="size-4 mr-1" />
|
||||||
|
Stop
|
||||||
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipPrimitive.Portal>
|
<TooltipPrimitive.Portal>
|
||||||
<TooltipContent sideOffset={5} className="z-[60]">
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
@@ -226,9 +225,23 @@ export const ShowGeneralPostgres = ({ postgresId }: Props) => {
|
|||||||
appName={data?.appName || ""}
|
appName={data?.appName || ""}
|
||||||
serverId={data?.serverId || ""}
|
serverId={data?.serverId || ""}
|
||||||
>
|
>
|
||||||
<Button variant="outline">
|
<Button
|
||||||
<Terminal />
|
variant="outline"
|
||||||
Open Terminal
|
className="flex items-center gap-1.5 focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
|
>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<div className="flex items-center">
|
||||||
|
<Terminal className="size-4 mr-1" />
|
||||||
|
Open Terminal
|
||||||
|
</div>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipPrimitive.Portal>
|
||||||
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
|
<p>Open a terminal to the PostgreSQL container</p>
|
||||||
|
</TooltipContent>
|
||||||
|
</TooltipPrimitive.Portal>
|
||||||
|
</Tooltip>
|
||||||
</Button>
|
</Button>
|
||||||
</DockerTerminalModal>
|
</DockerTerminalModal>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import { Input } from "@/components/ui/input";
|
|||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { PenBoxIcon } from "lucide-react";
|
import { PenBox } from "lucide-react";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
@@ -94,9 +94,9 @@ export const UpdatePostgres = ({ postgresId }: Props) => {
|
|||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="icon"
|
size="icon"
|
||||||
className="group hover:bg-blue-500/10 "
|
className="group hover:bg-blue-500/10 focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
>
|
>
|
||||||
<PenBoxIcon className="size-3.5 text-primary group-hover:text-blue-500" />
|
<PenBox className="size-3.5 text-primary group-hover:text-blue-500" />
|
||||||
</Button>
|
</Button>
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
<DialogContent className="max-h-screen overflow-y-auto sm:max-w-lg">
|
<DialogContent className="max-h-screen overflow-y-auto sm:max-w-lg">
|
||||||
@@ -151,6 +151,7 @@ export const UpdatePostgres = ({ postgresId }: Props) => {
|
|||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
form="hook-form-update-postgres"
|
form="hook-form-update-postgres"
|
||||||
type="submit"
|
type="submit"
|
||||||
|
className="flex items-center gap-1.5 focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
>
|
>
|
||||||
Update
|
Update
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const examples = [
|
|||||||
"Sendgrid service opensource analogue",
|
"Sendgrid service opensource analogue",
|
||||||
];
|
];
|
||||||
|
|
||||||
export const StepOne = ({ nextStep, setTemplateInfo, templateInfo }: any) => {
|
export const StepOne = ({ setTemplateInfo, templateInfo }: any) => {
|
||||||
// Get servers from the API
|
// Get servers from the API
|
||||||
const { data: servers } = api.server.withSSHKey.useQuery();
|
const { data: servers } = api.server.withSSHKey.useQuery();
|
||||||
|
|
||||||
|
|||||||
@@ -105,7 +105,10 @@ export const ShowExternalRedisCredentials = ({ redisId }: Props) => {
|
|||||||
{!getIp && (
|
{!getIp && (
|
||||||
<AlertBlock type="warning">
|
<AlertBlock type="warning">
|
||||||
You need to set an IP address in your{" "}
|
You need to set an IP address in your{" "}
|
||||||
<Link href="/dashboard/settings" className="text-primary">
|
<Link
|
||||||
|
href="/dashboard/settings/server"
|
||||||
|
className="text-primary"
|
||||||
|
>
|
||||||
{data?.serverId
|
{data?.serverId
|
||||||
? "Remote Servers -> Server -> Edit Server -> Update IP Address"
|
? "Remote Servers -> Server -> Edit Server -> Update IP Address"
|
||||||
: "Web Server -> Server -> Update Server IP"}
|
: "Web Server -> Server -> Update Server IP"}
|
||||||
|
|||||||
@@ -10,13 +10,7 @@ import {
|
|||||||
} from "@/components/ui/tooltip";
|
} from "@/components/ui/tooltip";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
||||||
import {
|
import { Ban, CheckCircle2, RefreshCcw, Rocket, Terminal } from "lucide-react";
|
||||||
Ban,
|
|
||||||
CheckCircle2,
|
|
||||||
HelpCircle,
|
|
||||||
RefreshCcw,
|
|
||||||
Terminal,
|
|
||||||
} from "lucide-react";
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { type LogLine, parseLogs } from "../../docker/logs/utils";
|
import { type LogLine, parseLogs } from "../../docker/logs/utils";
|
||||||
@@ -91,12 +85,14 @@ export const ShowGeneralRedis = ({ redisId }: Props) => {
|
|||||||
<Button
|
<Button
|
||||||
variant="default"
|
variant="default"
|
||||||
isLoading={data?.applicationStatus === "running"}
|
isLoading={data?.applicationStatus === "running"}
|
||||||
className="flex items-center gap-1.5"
|
className="flex items-center gap-1.5 focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
>
|
>
|
||||||
Deploy
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<HelpCircle className="size-4 text-muted-foreground hover:text-foreground transition-colors cursor-pointer" />
|
<div className="flex items-center">
|
||||||
|
<Rocket className="size-4 mr-1" />
|
||||||
|
Deploy
|
||||||
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipPrimitive.Portal>
|
<TooltipPrimitive.Portal>
|
||||||
<TooltipContent sideOffset={5} className="z-[60]">
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
@@ -127,13 +123,14 @@ export const ShowGeneralRedis = ({ redisId }: Props) => {
|
|||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
isLoading={isReloading}
|
isLoading={isReloading}
|
||||||
className="flex items-center gap-1.5"
|
className="flex items-center gap-1.5 focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
>
|
>
|
||||||
Reload
|
|
||||||
<RefreshCcw className="size-4" />
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<HelpCircle className="size-4 text-muted-foreground hover:text-foreground transition-colors cursor-pointer" />
|
<div className="flex items-center">
|
||||||
|
<RefreshCcw className="size-4 mr-1" />
|
||||||
|
Reload
|
||||||
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipPrimitive.Portal>
|
<TooltipPrimitive.Portal>
|
||||||
<TooltipContent sideOffset={5} className="z-[60]">
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
@@ -164,13 +161,14 @@ export const ShowGeneralRedis = ({ redisId }: Props) => {
|
|||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
isLoading={isStarting}
|
isLoading={isStarting}
|
||||||
className="flex items-center gap-1.5"
|
className="flex items-center gap-1.5 focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
>
|
>
|
||||||
Start
|
|
||||||
<CheckCircle2 className="size-4" />
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<HelpCircle className="size-4 text-muted-foreground hover:text-foreground transition-colors cursor-pointer" />
|
<div className="flex items-center">
|
||||||
|
<CheckCircle2 className="size-4 mr-1" />
|
||||||
|
Start
|
||||||
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipPrimitive.Portal>
|
<TooltipPrimitive.Portal>
|
||||||
<TooltipContent sideOffset={5} className="z-[60]">
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
@@ -203,13 +201,14 @@ export const ShowGeneralRedis = ({ redisId }: Props) => {
|
|||||||
<Button
|
<Button
|
||||||
variant="destructive"
|
variant="destructive"
|
||||||
isLoading={isStopping}
|
isLoading={isStopping}
|
||||||
className="flex items-center gap-1.5"
|
className="flex items-center gap-1.5 focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
>
|
>
|
||||||
Stop
|
|
||||||
<Ban className="size-4" />
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<HelpCircle className="size-4 text-muted-foreground hover:text-foreground transition-colors cursor-pointer" />
|
<div className="flex items-center">
|
||||||
|
<Ban className="size-4 mr-1" />
|
||||||
|
Stop
|
||||||
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipPrimitive.Portal>
|
<TooltipPrimitive.Portal>
|
||||||
<TooltipContent sideOffset={5} className="z-[60]">
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
@@ -225,9 +224,23 @@ export const ShowGeneralRedis = ({ redisId }: Props) => {
|
|||||||
appName={data?.appName || ""}
|
appName={data?.appName || ""}
|
||||||
serverId={data?.serverId || ""}
|
serverId={data?.serverId || ""}
|
||||||
>
|
>
|
||||||
<Button variant="outline">
|
<Button
|
||||||
<Terminal />
|
variant="outline"
|
||||||
Open Terminal
|
className="flex items-center gap-1.5 focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
|
>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<div className="flex items-center">
|
||||||
|
<Terminal className="size-4 mr-1" />
|
||||||
|
Open Terminal
|
||||||
|
</div>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipPrimitive.Portal>
|
||||||
|
<TooltipContent sideOffset={5} className="z-[60]">
|
||||||
|
<p>Open a terminal to the Redis container</p>
|
||||||
|
</TooltipContent>
|
||||||
|
</TooltipPrimitive.Portal>
|
||||||
|
</Tooltip>
|
||||||
</Button>
|
</Button>
|
||||||
</DockerTerminalModal>
|
</DockerTerminalModal>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|||||||
@@ -56,10 +56,10 @@ export const AddNode = ({ serverId }: Props) => {
|
|||||||
<TabsTrigger value="worker">Worker</TabsTrigger>
|
<TabsTrigger value="worker">Worker</TabsTrigger>
|
||||||
<TabsTrigger value="manager">Manager</TabsTrigger>
|
<TabsTrigger value="manager">Manager</TabsTrigger>
|
||||||
</TabsList>
|
</TabsList>
|
||||||
<TabsContent value="worker" className="pt-4">
|
<TabsContent value="worker" className="pt-4 overflow-hidden">
|
||||||
<AddWorker serverId={serverId} />
|
<AddWorker serverId={serverId} />
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
<TabsContent value="manager" className="pt-4">
|
<TabsContent value="manager" className="pt-4 overflow-hidden">
|
||||||
<AddManager serverId={serverId} />
|
<AddManager serverId={serverId} />
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { AlertBlock } from "@/components/shared/alert-block";
|
||||||
import { CardContent } from "@/components/ui/card";
|
import { CardContent } from "@/components/ui/card";
|
||||||
import {
|
import {
|
||||||
DialogDescription,
|
DialogDescription,
|
||||||
@@ -6,7 +7,7 @@ import {
|
|||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/dialog";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import copy from "copy-to-clipboard";
|
import copy from "copy-to-clipboard";
|
||||||
import { CopyIcon } from "lucide-react";
|
import { CopyIcon, Loader2 } from "lucide-react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -14,56 +15,66 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const AddManager = ({ serverId }: Props) => {
|
export const AddManager = ({ serverId }: Props) => {
|
||||||
const { data } = api.cluster.addManager.useQuery({ serverId });
|
const { data, isLoading, error, isError } = api.cluster.addManager.useQuery({
|
||||||
|
serverId,
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div>
|
<CardContent className="sm:max-w-4xl flex flex-col gap-4 px-0">
|
||||||
<CardContent className="sm:max-w-4xl max-h-screen overflow-y-auto flex flex-col gap-4 px-0">
|
<DialogHeader>
|
||||||
<DialogHeader>
|
<DialogTitle>Add a new manager</DialogTitle>
|
||||||
<DialogTitle>Add a new manager</DialogTitle>
|
<DialogDescription>Add a new manager</DialogDescription>
|
||||||
<DialogDescription>Add a new manager</DialogDescription>
|
</DialogHeader>
|
||||||
</DialogHeader>
|
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
|
||||||
<div className="flex flex-col gap-2.5 text-sm">
|
{isLoading ? (
|
||||||
<span>1. Go to your new server and run the following command</span>
|
<Loader2 className="w-full animate-spin text-muted-foreground" />
|
||||||
<span className="bg-muted rounded-lg p-2 flex justify-between">
|
) : (
|
||||||
curl https://get.docker.com | sh -s -- --version {data?.version}
|
<>
|
||||||
<button
|
<div className="flex flex-col gap-2.5 text-sm">
|
||||||
type="button"
|
<span>
|
||||||
className="self-center"
|
1. Go to your new server and run the following command
|
||||||
onClick={() => {
|
</span>
|
||||||
copy(
|
<span className="bg-muted rounded-lg p-2 flex justify-between">
|
||||||
`curl https://get.docker.com | sh -s -- --version ${data?.version}`,
|
curl https://get.docker.com | sh -s -- --version {data?.version}
|
||||||
);
|
<button
|
||||||
toast.success("Copied to clipboard");
|
type="button"
|
||||||
}}
|
className="self-center"
|
||||||
>
|
onClick={() => {
|
||||||
<CopyIcon className="h-4 w-4 cursor-pointer" />
|
copy(
|
||||||
</button>
|
`curl https://get.docker.com | sh -s -- --version ${data?.version}`,
|
||||||
</span>
|
);
|
||||||
</div>
|
toast.success("Copied to clipboard");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CopyIcon className="h-4 w-4 cursor-pointer" />
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col gap-2.5 text-sm">
|
<div className="flex flex-col gap-2.5 text-sm">
|
||||||
<span>
|
<span>
|
||||||
2. Run the following command to add the node(manager) to your
|
2. Run the following command to add the node(manager) to your
|
||||||
cluster
|
cluster
|
||||||
</span>
|
</span>
|
||||||
<span className="bg-muted rounded-lg p-2 flex">
|
|
||||||
{data?.command}
|
<span className="bg-muted rounded-lg p-2 flex">
|
||||||
<button
|
{data?.command}
|
||||||
type="button"
|
<button
|
||||||
className="self-start"
|
type="button"
|
||||||
onClick={() => {
|
className="self-start"
|
||||||
copy(data?.command || "");
|
onClick={() => {
|
||||||
toast.success("Copied to clipboard");
|
copy(data?.command || "");
|
||||||
}}
|
toast.success("Copied to clipboard");
|
||||||
>
|
}}
|
||||||
<CopyIcon className="h-4 w-4 cursor-pointer" />
|
>
|
||||||
</button>
|
<CopyIcon className="h-4 w-4 cursor-pointer" />
|
||||||
</span>
|
</button>
|
||||||
</div>
|
</span>
|
||||||
</CardContent>
|
</div>
|
||||||
</div>
|
</>
|
||||||
|
)}
|
||||||
|
</CardContent>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export const ShowNodesModal = ({ serverId }: Props) => {
|
|||||||
className="w-full cursor-pointer "
|
className="w-full cursor-pointer "
|
||||||
onSelect={(e) => e.preventDefault()}
|
onSelect={(e) => e.preventDefault()}
|
||||||
>
|
>
|
||||||
Show Nodes
|
Show Swarm Nodes
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
<DialogContent className="sm:max-w-5xl overflow-y-auto max-h-screen ">
|
<DialogContent className="sm:max-w-5xl overflow-y-auto max-h-screen ">
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { AlertBlock } from "@/components/shared/alert-block";
|
||||||
import { CardContent } from "@/components/ui/card";
|
import { CardContent } from "@/components/ui/card";
|
||||||
import {
|
import {
|
||||||
DialogDescription,
|
DialogDescription,
|
||||||
@@ -6,7 +7,7 @@ import {
|
|||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/dialog";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import copy from "copy-to-clipboard";
|
import copy from "copy-to-clipboard";
|
||||||
import { CopyIcon } from "lucide-react";
|
import { CopyIcon, Loader2 } from "lucide-react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -14,54 +15,62 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const AddWorker = ({ serverId }: Props) => {
|
export const AddWorker = ({ serverId }: Props) => {
|
||||||
const { data } = api.cluster.addWorker.useQuery({ serverId });
|
const { data, isLoading, error, isError } = api.cluster.addWorker.useQuery({
|
||||||
|
serverId,
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<CardContent className="sm:max-w-4xl flex flex-col gap-4 px-0">
|
||||||
<CardContent className="sm:max-w-4xl max-h-screen overflow-y-auto flex flex-col gap-4 px-0">
|
<DialogHeader>
|
||||||
<DialogHeader>
|
<DialogTitle>Add a new worker</DialogTitle>
|
||||||
<DialogTitle>Add a new worker</DialogTitle>
|
<DialogDescription>Add a new worker</DialogDescription>
|
||||||
<DialogDescription>Add a new worker</DialogDescription>
|
</DialogHeader>
|
||||||
</DialogHeader>
|
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
|
||||||
<div className="flex flex-col gap-2.5 text-sm">
|
{isLoading ? (
|
||||||
<span>1. Go to your new server and run the following command</span>
|
<Loader2 className="w-full animate-spin text-muted-foreground" />
|
||||||
<span className="bg-muted rounded-lg p-2 flex justify-between">
|
) : (
|
||||||
curl https://get.docker.com | sh -s -- --version {data?.version}
|
<>
|
||||||
<button
|
<div className="flex flex-col gap-2.5 text-sm">
|
||||||
type="button"
|
<span>1. Go to your new server and run the following command</span>
|
||||||
className="self-center"
|
<span className="bg-muted rounded-lg p-2 flex justify-between">
|
||||||
onClick={() => {
|
curl https://get.docker.com | sh -s -- --version {data?.version}
|
||||||
copy(
|
<button
|
||||||
`curl https://get.docker.com | sh -s -- --version ${data?.version}`,
|
type="button"
|
||||||
);
|
className="self-center"
|
||||||
toast.success("Copied to clipboard");
|
onClick={() => {
|
||||||
}}
|
copy(
|
||||||
>
|
`curl https://get.docker.com | sh -s -- --version ${data?.version}`,
|
||||||
<CopyIcon className="h-4 w-4 cursor-pointer" />
|
);
|
||||||
</button>
|
toast.success("Copied to clipboard");
|
||||||
</span>
|
}}
|
||||||
</div>
|
>
|
||||||
|
<CopyIcon className="h-4 w-4 cursor-pointer" />
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col gap-2.5 text-sm">
|
<div className="flex flex-col gap-2.5 text-sm">
|
||||||
<span>
|
<span>
|
||||||
2. Run the following command to add the node(worker) to your cluster
|
2. Run the following command to add the node(worker) to your
|
||||||
</span>
|
cluster
|
||||||
|
</span>
|
||||||
|
|
||||||
<span className="bg-muted rounded-lg p-2 flex">
|
<span className="bg-muted rounded-lg p-2 flex">
|
||||||
{data?.command}
|
{data?.command}
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="self-start"
|
className="self-start"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
copy(data?.command || "");
|
copy(data?.command || "");
|
||||||
toast.success("Copied to clipboard");
|
toast.success("Copied to clipboard");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CopyIcon className="h-4 w-4 cursor-pointer" />
|
<CopyIcon className="h-4 w-4 cursor-pointer" />
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</>
|
||||||
</div>
|
)}
|
||||||
|
</CardContent>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -139,7 +139,10 @@ export const AddGiteaProvider = () => {
|
|||||||
<ExternalLink className="w-fit text-primary size-4" />
|
<ExternalLink className="w-fit text-primary size-4" />
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
<li>Navigate to Applications</li>
|
<li>
|
||||||
|
Navigate to Applications {"->"} Create new OAuth2
|
||||||
|
Application
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
Create a new application with the following details:
|
Create a new application with the following details:
|
||||||
<ul className="list-disc list-inside ml-4">
|
<ul className="list-disc list-inside ml-4">
|
||||||
@@ -148,10 +151,6 @@ export const AddGiteaProvider = () => {
|
|||||||
Redirect URI:{" "}
|
Redirect URI:{" "}
|
||||||
<span className="text-primary">{webhookUrl}</span>{" "}
|
<span className="text-primary">{webhookUrl}</span>{" "}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
Select Permissions - organization: read, user: read,
|
|
||||||
repository: read/write
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|||||||
@@ -124,10 +124,10 @@ export const ShowGitProviders = () => {
|
|||||||
gitProvider.gitlab?.accessToken &&
|
gitProvider.gitlab?.accessToken &&
|
||||||
gitProvider.gitlab?.refreshToken;
|
gitProvider.gitlab?.refreshToken;
|
||||||
|
|
||||||
const haveGiteaRequirements =
|
// const haveGiteaRequirements =
|
||||||
isGitea &&
|
// isGitea &&
|
||||||
gitProvider.gitea?.accessToken &&
|
// gitProvider.gitea?.accessToken &&
|
||||||
gitProvider.gitea?.refreshToken;
|
// gitProvider.gitea?.refreshToken;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -207,6 +207,7 @@ export const ShowGitProviders = () => {
|
|||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isGithub && haveGithubRequirements && (
|
{isGithub && haveGithubRequirements && (
|
||||||
<EditGithubProvider
|
<EditGithubProvider
|
||||||
githubId={gitProvider.github?.githubId}
|
githubId={gitProvider.github?.githubId}
|
||||||
|
|||||||
@@ -663,13 +663,16 @@ export const HandleNotifications = ({ notificationId }: Props) => {
|
|||||||
{...field}
|
{...field}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const value = e.target.value;
|
const value = e.target.value;
|
||||||
if (value) {
|
if (value === "") {
|
||||||
|
field.onChange(undefined);
|
||||||
|
} else {
|
||||||
const port = Number.parseInt(value);
|
const port = Number.parseInt(value);
|
||||||
if (port > 0 && port < 65536) {
|
if (port > 0 && port < 65536) {
|
||||||
field.onChange(port);
|
field.onChange(port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
value={field.value || ""}
|
||||||
type="number"
|
type="number"
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|||||||
@@ -159,9 +159,11 @@ export const ManageTraefikPorts = ({ children, serverId }: Props) => {
|
|||||||
<Input
|
<Input
|
||||||
type="number"
|
type="number"
|
||||||
{...field}
|
{...field}
|
||||||
onChange={(e) =>
|
onChange={(e) => {
|
||||||
field.onChange(Number(e.target.value))
|
const value = e.target.value;
|
||||||
}
|
field.onChange(value === "" ? undefined : Number(value));
|
||||||
|
}}
|
||||||
|
value={field.value || ""}
|
||||||
className="w-full dark:bg-black"
|
className="w-full dark:bg-black"
|
||||||
placeholder="e.g. 8080"
|
placeholder="e.g. 8080"
|
||||||
/>
|
/>
|
||||||
@@ -185,9 +187,11 @@ export const ManageTraefikPorts = ({ children, serverId }: Props) => {
|
|||||||
<Input
|
<Input
|
||||||
type="number"
|
type="number"
|
||||||
{...field}
|
{...field}
|
||||||
onChange={(e) =>
|
onChange={(e) => {
|
||||||
field.onChange(Number(e.target.value))
|
const value = e.target.value;
|
||||||
}
|
field.onChange(value === "" ? undefined : Number(value));
|
||||||
|
}}
|
||||||
|
value={field.value || ""}
|
||||||
className="w-full dark:bg-black"
|
className="w-full dark:bg-black"
|
||||||
placeholder="e.g. 80"
|
placeholder="e.g. 80"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
ALTER TYPE "public"."gitProviderType" ADD VALUE 'gitea';--> statement-breakpoint
|
|
||||||
CREATE TABLE "gitea" (
|
|
||||||
"giteaId" text PRIMARY KEY NOT NULL,
|
|
||||||
"giteaUrl" text DEFAULT 'https://gitea.com' NOT NULL,
|
|
||||||
"application_id" text,
|
|
||||||
"redirect_uri" text,
|
|
||||||
"secret" text,
|
|
||||||
"access_token" text,
|
|
||||||
"refresh_token" text,
|
|
||||||
"organization_name" text,
|
|
||||||
"expires_at" integer,
|
|
||||||
"gitProviderId" text NOT NULL,
|
|
||||||
"gitea_username" text
|
|
||||||
);
|
|
||||||
--> statement-breakpoint
|
|
||||||
ALTER TABLE "gitea" ADD CONSTRAINT "gitea_gitProviderId_git_provider_gitProviderId_fk" FOREIGN KEY ("gitProviderId") REFERENCES "public"."git_provider"("gitProviderId") ON DELETE cascade ON UPDATE no action;
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
ALTER TYPE "public"."sourceType" ADD VALUE 'gitea' BEFORE 'drop';--> statement-breakpoint
|
|
||||||
ALTER TABLE "application" ADD COLUMN "giteaProjectId" integer;--> statement-breakpoint
|
|
||||||
ALTER TABLE "application" ADD COLUMN "giteaRepository" text;--> statement-breakpoint
|
|
||||||
ALTER TABLE "application" ADD COLUMN "giteaOwner" text;--> statement-breakpoint
|
|
||||||
ALTER TABLE "application" ADD COLUMN "giteaBranch" text;--> statement-breakpoint
|
|
||||||
ALTER TABLE "application" ADD COLUMN "giteaBuildPath" text DEFAULT '/';--> statement-breakpoint
|
|
||||||
ALTER TABLE "application" ADD COLUMN "giteaPathNamespace" text;--> statement-breakpoint
|
|
||||||
ALTER TABLE "application" ADD COLUMN "giteaId" text;--> statement-breakpoint
|
|
||||||
ALTER TABLE "application" ADD CONSTRAINT "application_giteaId_gitea_giteaId_fk" FOREIGN KEY ("giteaId") REFERENCES "public"."gitea"("giteaId") ON DELETE set null ON UPDATE no action;
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
ALTER TABLE "gitea" ADD COLUMN "client_id" text;--> statement-breakpoint
|
|
||||||
ALTER TABLE "gitea" ADD COLUMN "client_secret" text;--> statement-breakpoint
|
|
||||||
ALTER TABLE "gitea" DROP COLUMN "application_id";--> statement-breakpoint
|
|
||||||
ALTER TABLE "gitea" DROP COLUMN "secret";--> statement-breakpoint
|
|
||||||
ALTER TABLE "gitea" DROP COLUMN "refresh_token";--> statement-breakpoint
|
|
||||||
ALTER TABLE "gitea" DROP COLUMN "organization_name";
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
ALTER TABLE "gitea" ADD COLUMN "refresh_token" text;--> statement-breakpoint
|
|
||||||
ALTER TABLE "gitea" ADD COLUMN "organization_name" text;--> statement-breakpoint
|
|
||||||
ALTER TABLE "gitea" ADD COLUMN "scopes" text;--> statement-breakpoint
|
|
||||||
ALTER TABLE "gitea" ADD COLUMN "last_authenticated_at" integer;
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
ALTER TYPE "public"."sourceTypeCompose" ADD VALUE 'gitea' BEFORE 'raw';--> statement-breakpoint
|
|
||||||
ALTER TABLE "compose" ADD COLUMN "giteaRepository" text;--> statement-breakpoint
|
|
||||||
ALTER TABLE "compose" ADD COLUMN "giteaOwner" text;--> statement-breakpoint
|
|
||||||
ALTER TABLE "compose" ADD COLUMN "giteaBranch" text;--> statement-breakpoint
|
|
||||||
ALTER TABLE "compose" ADD COLUMN "giteaId" text;--> statement-breakpoint
|
|
||||||
ALTER TABLE "compose" ADD CONSTRAINT "compose_giteaId_gitea_giteaId_fk" FOREIGN KEY ("giteaId") REFERENCES "public"."gitea"("giteaId") ON DELETE set null ON UPDATE no action;
|
|
||||||
@@ -1,157 +0,0 @@
|
|||||||
DO $$
|
|
||||||
BEGIN
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM pg_enum WHERE enumlabel = 'gitea' AND
|
|
||||||
enumtypid = (SELECT oid FROM pg_type WHERE typname = 'sourceType')) THEN
|
|
||||||
ALTER TYPE "public"."sourceType" ADD VALUE 'gitea' BEFORE 'drop';
|
|
||||||
END IF;
|
|
||||||
END
|
|
||||||
$$;
|
|
||||||
|
|
||||||
DO $$
|
|
||||||
BEGIN
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM pg_enum WHERE enumlabel = 'gitea' AND
|
|
||||||
enumtypid = (SELECT oid FROM pg_type WHERE typname = 'sourceTypeCompose')) THEN
|
|
||||||
ALTER TYPE "public"."sourceTypeCompose" ADD VALUE 'gitea' BEFORE 'raw';
|
|
||||||
END IF;
|
|
||||||
END
|
|
||||||
$$;
|
|
||||||
|
|
||||||
DO $$
|
|
||||||
BEGIN
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM pg_enum WHERE enumlabel = 'gitea' AND
|
|
||||||
enumtypid = (SELECT oid FROM pg_type WHERE typname = 'gitProviderType')) THEN
|
|
||||||
ALTER TYPE "public"."gitProviderType" ADD VALUE 'gitea';
|
|
||||||
END IF;
|
|
||||||
END
|
|
||||||
$$;
|
|
||||||
DO $$
|
|
||||||
BEGIN
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'gitea') THEN
|
|
||||||
CREATE TABLE "gitea" (
|
|
||||||
"giteaId" text PRIMARY KEY NOT NULL,
|
|
||||||
"giteaUrl" text DEFAULT 'https://gitea.com' NOT NULL,
|
|
||||||
"redirect_uri" text,
|
|
||||||
"client_id" text,
|
|
||||||
"client_secret" text,
|
|
||||||
"gitProviderId" text NOT NULL,
|
|
||||||
"gitea_username" text,
|
|
||||||
"access_token" text,
|
|
||||||
"refresh_token" text,
|
|
||||||
"expires_at" integer,
|
|
||||||
"scopes" text DEFAULT 'repo,repo:status,read:user,read:org',
|
|
||||||
"last_authenticated_at" integer
|
|
||||||
);
|
|
||||||
END IF;
|
|
||||||
END
|
|
||||||
$$;
|
|
||||||
--> statement-breakpoint
|
|
||||||
DO $$
|
|
||||||
BEGIN
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'application' AND column_name = 'giteaProjectId') THEN
|
|
||||||
ALTER TABLE "application" ADD COLUMN "giteaProjectId" integer;
|
|
||||||
END IF;
|
|
||||||
END $$;
|
|
||||||
|
|
||||||
DO $$
|
|
||||||
BEGIN
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'application' AND column_name = 'giteaRepository') THEN
|
|
||||||
ALTER TABLE "application" ADD COLUMN "giteaRepository" text;
|
|
||||||
END IF;
|
|
||||||
END $$;
|
|
||||||
|
|
||||||
DO $$
|
|
||||||
BEGIN
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'application' AND column_name = 'giteaOwner') THEN
|
|
||||||
ALTER TABLE "application" ADD COLUMN "giteaOwner" text;
|
|
||||||
END IF;
|
|
||||||
END $$;
|
|
||||||
|
|
||||||
DO $$
|
|
||||||
BEGIN
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'application' AND column_name = 'giteaBranch') THEN
|
|
||||||
ALTER TABLE "application" ADD COLUMN "giteaBranch" text;
|
|
||||||
END IF;
|
|
||||||
END $$;
|
|
||||||
|
|
||||||
DO $$
|
|
||||||
BEGIN
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'application' AND column_name = 'giteaBuildPath') THEN
|
|
||||||
ALTER TABLE "application" ADD COLUMN "giteaBuildPath" text DEFAULT '/';
|
|
||||||
END IF;
|
|
||||||
END $$;
|
|
||||||
|
|
||||||
DO $$
|
|
||||||
BEGIN
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'application' AND column_name = 'giteaPathNamespace') THEN
|
|
||||||
ALTER TABLE "application" ADD COLUMN "giteaPathNamespace" text;
|
|
||||||
END IF;
|
|
||||||
END $$;
|
|
||||||
|
|
||||||
DO $$
|
|
||||||
BEGIN
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'application' AND column_name = 'giteaId') THEN
|
|
||||||
ALTER TABLE "application" ADD COLUMN "giteaId" text;
|
|
||||||
END IF;
|
|
||||||
END $$;
|
|
||||||
DO $$
|
|
||||||
BEGIN
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'compose' AND column_name = 'giteaRepository') THEN
|
|
||||||
ALTER TABLE "compose" ADD COLUMN "giteaRepository" text;
|
|
||||||
END IF;
|
|
||||||
END $$;
|
|
||||||
|
|
||||||
DO $$
|
|
||||||
BEGIN
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'compose' AND column_name = 'giteaOwner') THEN
|
|
||||||
ALTER TABLE "compose" ADD COLUMN "giteaOwner" text;
|
|
||||||
END IF;
|
|
||||||
END $$;
|
|
||||||
|
|
||||||
DO $$
|
|
||||||
BEGIN
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'compose' AND column_name = 'giteaBranch') THEN
|
|
||||||
ALTER TABLE "compose" ADD COLUMN "giteaBranch" text;
|
|
||||||
END IF;
|
|
||||||
END $$;
|
|
||||||
|
|
||||||
DO $$
|
|
||||||
BEGIN
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'compose' AND column_name = 'giteaId') THEN
|
|
||||||
ALTER TABLE "compose" ADD COLUMN "giteaId" text;
|
|
||||||
END IF;
|
|
||||||
END $$;
|
|
||||||
DO $$
|
|
||||||
BEGIN
|
|
||||||
IF NOT EXISTS (
|
|
||||||
SELECT 1 FROM information_schema.table_constraints
|
|
||||||
WHERE constraint_name = 'gitea_gitProviderId_git_provider_gitProviderId_fk'
|
|
||||||
) THEN
|
|
||||||
ALTER TABLE "gitea" ADD CONSTRAINT "gitea_gitProviderId_git_provider_gitProviderId_fk"
|
|
||||||
FOREIGN KEY ("gitProviderId") REFERENCES "public"."git_provider"("gitProviderId")
|
|
||||||
ON DELETE cascade ON UPDATE no action;
|
|
||||||
END IF;
|
|
||||||
END $$;
|
|
||||||
|
|
||||||
DO $$
|
|
||||||
BEGIN
|
|
||||||
IF NOT EXISTS (
|
|
||||||
SELECT 1 FROM information_schema.table_constraints
|
|
||||||
WHERE constraint_name = 'application_giteaId_gitea_giteaId_fk'
|
|
||||||
) THEN
|
|
||||||
ALTER TABLE "application" ADD CONSTRAINT "application_giteaId_gitea_giteaId_fk"
|
|
||||||
FOREIGN KEY ("giteaId") REFERENCES "public"."gitea"("giteaId")
|
|
||||||
ON DELETE set null ON UPDATE no action;
|
|
||||||
END IF;
|
|
||||||
END $$;
|
|
||||||
|
|
||||||
DO $$
|
|
||||||
BEGIN
|
|
||||||
IF NOT EXISTS (
|
|
||||||
SELECT 1 FROM information_schema.table_constraints
|
|
||||||
WHERE constraint_name = 'compose_giteaId_gitea_giteaId_fk'
|
|
||||||
) THEN
|
|
||||||
ALTER TABLE "compose" ADD CONSTRAINT "compose_giteaId_gitea_giteaId_fk"
|
|
||||||
FOREIGN KEY ("giteaId") REFERENCES "public"."gitea"("giteaId")
|
|
||||||
ON DELETE set null ON UPDATE no action;
|
|
||||||
END IF;
|
|
||||||
END $$;
|
|
||||||
32
apps/dokploy/drizzle/0079_bizarre_wendell_rand.sql
Normal file
32
apps/dokploy/drizzle/0079_bizarre_wendell_rand.sql
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
ALTER TYPE "public"."sourceType" ADD VALUE 'gitea' BEFORE 'drop';--> statement-breakpoint
|
||||||
|
ALTER TYPE "public"."sourceTypeCompose" ADD VALUE 'gitea' BEFORE 'raw';--> statement-breakpoint
|
||||||
|
ALTER TYPE "public"."gitProviderType" ADD VALUE 'gitea';--> statement-breakpoint
|
||||||
|
CREATE TABLE "gitea" (
|
||||||
|
"giteaId" text PRIMARY KEY NOT NULL,
|
||||||
|
"giteaUrl" text DEFAULT 'https://gitea.com' NOT NULL,
|
||||||
|
"redirect_uri" text,
|
||||||
|
"client_id" text,
|
||||||
|
"client_secret" text,
|
||||||
|
"gitProviderId" text NOT NULL,
|
||||||
|
"gitea_username" text,
|
||||||
|
"access_token" text,
|
||||||
|
"refresh_token" text,
|
||||||
|
"expires_at" integer,
|
||||||
|
"scopes" text DEFAULT 'repo,repo:status,read:user,read:org',
|
||||||
|
"last_authenticated_at" integer
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
ALTER TABLE "application" ADD COLUMN "giteaProjectId" integer;--> statement-breakpoint
|
||||||
|
ALTER TABLE "application" ADD COLUMN "giteaRepository" text;--> statement-breakpoint
|
||||||
|
ALTER TABLE "application" ADD COLUMN "giteaOwner" text;--> statement-breakpoint
|
||||||
|
ALTER TABLE "application" ADD COLUMN "giteaBranch" text;--> statement-breakpoint
|
||||||
|
ALTER TABLE "application" ADD COLUMN "giteaBuildPath" text DEFAULT '/';--> statement-breakpoint
|
||||||
|
ALTER TABLE "application" ADD COLUMN "giteaPathNamespace" text;--> statement-breakpoint
|
||||||
|
ALTER TABLE "application" ADD COLUMN "giteaId" text;--> statement-breakpoint
|
||||||
|
ALTER TABLE "compose" ADD COLUMN "giteaRepository" text;--> statement-breakpoint
|
||||||
|
ALTER TABLE "compose" ADD COLUMN "giteaOwner" text;--> statement-breakpoint
|
||||||
|
ALTER TABLE "compose" ADD COLUMN "giteaBranch" text;--> statement-breakpoint
|
||||||
|
ALTER TABLE "compose" ADD COLUMN "giteaId" text;--> statement-breakpoint
|
||||||
|
ALTER TABLE "gitea" ADD CONSTRAINT "gitea_gitProviderId_git_provider_gitProviderId_fk" FOREIGN KEY ("gitProviderId") REFERENCES "public"."git_provider"("gitProviderId") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||||
|
ALTER TABLE "application" ADD CONSTRAINT "application_giteaId_gitea_giteaId_fk" FOREIGN KEY ("giteaId") REFERENCES "public"."gitea"("giteaId") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||||
|
ALTER TABLE "compose" ADD CONSTRAINT "compose_giteaId_gitea_giteaId_fk" FOREIGN KEY ("giteaId") REFERENCES "public"."gitea"("giteaId") ON DELETE set null ON UPDATE no action;
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"id": "436368c7-e9a2-4df0-8c8f-863a69c9432d",
|
"id": "44cb886c-d31a-4b3d-b70e-da306c74dcf5",
|
||||||
"prevId": "53fc370e-731b-4bfe-874f-9ce725650082",
|
"prevId": "53fc370e-731b-4bfe-874f-9ce725650082",
|
||||||
"version": "7",
|
"version": "7",
|
||||||
"dialect": "postgresql",
|
"dialect": "postgresql",
|
||||||
@@ -868,6 +868,12 @@
|
|||||||
"notNull": true,
|
"notNull": true,
|
||||||
"default": false
|
"default": false
|
||||||
},
|
},
|
||||||
|
"logCleanupCron": {
|
||||||
|
"name": "logCleanupCron",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
"enablePaidFeatures": {
|
"enablePaidFeatures": {
|
||||||
"name": "enablePaidFeatures",
|
"name": "enablePaidFeatures",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
@@ -3914,100 +3920,6 @@
|
|||||||
"checkConstraints": {},
|
"checkConstraints": {},
|
||||||
"isRLSEnabled": false
|
"isRLSEnabled": false
|
||||||
},
|
},
|
||||||
"public.gitea": {
|
|
||||||
"name": "gitea",
|
|
||||||
"schema": "",
|
|
||||||
"columns": {
|
|
||||||
"giteaId": {
|
|
||||||
"name": "giteaId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"giteaUrl": {
|
|
||||||
"name": "giteaUrl",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"default": "'https://gitea.com'"
|
|
||||||
},
|
|
||||||
"application_id": {
|
|
||||||
"name": "application_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"redirect_uri": {
|
|
||||||
"name": "redirect_uri",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"secret": {
|
|
||||||
"name": "secret",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"access_token": {
|
|
||||||
"name": "access_token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"refresh_token": {
|
|
||||||
"name": "refresh_token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"organization_name": {
|
|
||||||
"name": "organization_name",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"expires_at": {
|
|
||||||
"name": "expires_at",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"gitProviderId": {
|
|
||||||
"name": "gitProviderId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"gitea_username": {
|
|
||||||
"name": "gitea_username",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {
|
|
||||||
"gitea_gitProviderId_git_provider_gitProviderId_fk": {
|
|
||||||
"name": "gitea_gitProviderId_git_provider_gitProviderId_fk",
|
|
||||||
"tableFrom": "gitea",
|
|
||||||
"tableTo": "git_provider",
|
|
||||||
"columnsFrom": [
|
|
||||||
"gitProviderId"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"gitProviderId"
|
|
||||||
],
|
|
||||||
"onDelete": "cascade",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {},
|
|
||||||
"policies": {},
|
|
||||||
"checkConstraints": {},
|
|
||||||
"isRLSEnabled": false
|
|
||||||
},
|
|
||||||
"public.server": {
|
"public.server": {
|
||||||
"name": "server",
|
"name": "server",
|
||||||
"schema": "",
|
"schema": "",
|
||||||
@@ -5195,8 +5107,7 @@
|
|||||||
"values": [
|
"values": [
|
||||||
"github",
|
"github",
|
||||||
"gitlab",
|
"gitlab",
|
||||||
"bitbucket",
|
"bitbucket"
|
||||||
"gitea"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"public.serverStatus": {
|
"public.serverStatus": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"id": "4360a233-2c88-4d6c-834f-eef562e079e3",
|
"id": "ad43c733-01c3-4841-b600-252421350fb9",
|
||||||
"prevId": "436368c7-e9a2-4df0-8c8f-863a69c9432d",
|
"prevId": "44cb886c-d31a-4b3d-b70e-da306c74dcf5",
|
||||||
"version": "7",
|
"version": "7",
|
||||||
"dialect": "postgresql",
|
"dialect": "postgresql",
|
||||||
"tables": {
|
"tables": {
|
||||||
@@ -235,43 +235,6 @@
|
|||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": false
|
"notNull": false
|
||||||
},
|
},
|
||||||
"giteaProjectId": {
|
|
||||||
"name": "giteaProjectId",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"giteaRepository": {
|
|
||||||
"name": "giteaRepository",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"giteaOwner": {
|
|
||||||
"name": "giteaOwner",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"giteaBranch": {
|
|
||||||
"name": "giteaBranch",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"giteaBuildPath": {
|
|
||||||
"name": "giteaBuildPath",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"default": "'/'"
|
|
||||||
},
|
|
||||||
"giteaPathNamespace": {
|
|
||||||
"name": "giteaPathNamespace",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"bitbucketRepository": {
|
"bitbucketRepository": {
|
||||||
"name": "bitbucketRepository",
|
"name": "bitbucketRepository",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -483,12 +446,6 @@
|
|||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": false
|
"notNull": false
|
||||||
},
|
},
|
||||||
"giteaId": {
|
|
||||||
"name": "giteaId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"bitbucketId": {
|
"bitbucketId": {
|
||||||
"name": "bitbucketId",
|
"name": "bitbucketId",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -569,19 +526,6 @@
|
|||||||
"onDelete": "set null",
|
"onDelete": "set null",
|
||||||
"onUpdate": "no action"
|
"onUpdate": "no action"
|
||||||
},
|
},
|
||||||
"application_giteaId_gitea_giteaId_fk": {
|
|
||||||
"name": "application_giteaId_gitea_giteaId_fk",
|
|
||||||
"tableFrom": "application",
|
|
||||||
"tableTo": "gitea",
|
|
||||||
"columnsFrom": [
|
|
||||||
"giteaId"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"giteaId"
|
|
||||||
],
|
|
||||||
"onDelete": "set null",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
},
|
|
||||||
"application_bitbucketId_bitbucket_bitbucketId_fk": {
|
"application_bitbucketId_bitbucket_bitbucketId_fk": {
|
||||||
"name": "application_bitbucketId_bitbucket_bitbucketId_fk",
|
"name": "application_bitbucketId_bitbucket_bitbucketId_fk",
|
||||||
"tableFrom": "application",
|
"tableFrom": "application",
|
||||||
@@ -917,13 +861,6 @@
|
|||||||
"notNull": true,
|
"notNull": true,
|
||||||
"default": false
|
"default": false
|
||||||
},
|
},
|
||||||
"enableLogRotation": {
|
|
||||||
"name": "enableLogRotation",
|
|
||||||
"type": "boolean",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"default": false
|
|
||||||
},
|
|
||||||
"logCleanupCron": {
|
"logCleanupCron": {
|
||||||
"name": "logCleanupCron",
|
"name": "logCleanupCron",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -1153,6 +1090,12 @@
|
|||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": true,
|
"notNull": true,
|
||||||
"default": "'none'"
|
"default": "'none'"
|
||||||
|
},
|
||||||
|
"customCertResolver": {
|
||||||
|
"name": "customCertResolver",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"indexes": {},
|
"indexes": {},
|
||||||
@@ -3976,100 +3919,6 @@
|
|||||||
"checkConstraints": {},
|
"checkConstraints": {},
|
||||||
"isRLSEnabled": false
|
"isRLSEnabled": false
|
||||||
},
|
},
|
||||||
"public.gitea": {
|
|
||||||
"name": "gitea",
|
|
||||||
"schema": "",
|
|
||||||
"columns": {
|
|
||||||
"giteaId": {
|
|
||||||
"name": "giteaId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"giteaUrl": {
|
|
||||||
"name": "giteaUrl",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"default": "'https://gitea.com'"
|
|
||||||
},
|
|
||||||
"application_id": {
|
|
||||||
"name": "application_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"redirect_uri": {
|
|
||||||
"name": "redirect_uri",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"secret": {
|
|
||||||
"name": "secret",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"access_token": {
|
|
||||||
"name": "access_token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"refresh_token": {
|
|
||||||
"name": "refresh_token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"organization_name": {
|
|
||||||
"name": "organization_name",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"expires_at": {
|
|
||||||
"name": "expires_at",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"gitProviderId": {
|
|
||||||
"name": "gitProviderId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"gitea_username": {
|
|
||||||
"name": "gitea_username",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {
|
|
||||||
"gitea_gitProviderId_git_provider_gitProviderId_fk": {
|
|
||||||
"name": "gitea_gitProviderId_git_provider_gitProviderId_fk",
|
|
||||||
"tableFrom": "gitea",
|
|
||||||
"tableTo": "git_provider",
|
|
||||||
"columnsFrom": [
|
|
||||||
"gitProviderId"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"gitProviderId"
|
|
||||||
],
|
|
||||||
"onDelete": "cascade",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {},
|
|
||||||
"policies": {},
|
|
||||||
"checkConstraints": {},
|
|
||||||
"isRLSEnabled": false
|
|
||||||
},
|
|
||||||
"public.server": {
|
"public.server": {
|
||||||
"name": "server",
|
"name": "server",
|
||||||
"schema": "",
|
"schema": "",
|
||||||
@@ -5134,7 +4983,6 @@
|
|||||||
"github",
|
"github",
|
||||||
"gitlab",
|
"gitlab",
|
||||||
"bitbucket",
|
"bitbucket",
|
||||||
"gitea",
|
|
||||||
"drop"
|
"drop"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -5259,8 +5107,7 @@
|
|||||||
"values": [
|
"values": [
|
||||||
"github",
|
"github",
|
||||||
"gitlab",
|
"gitlab",
|
||||||
"bitbucket",
|
"bitbucket"
|
||||||
"gitea"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"public.serverStatus": {
|
"public.serverStatus": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"id": "8946105c-e69c-49c7-8334-784ee2419a92",
|
"id": "5808aed9-4223-4ac4-ae22-6c0dae500d75",
|
||||||
"prevId": "4360a233-2c88-4d6c-834f-eef562e079e3",
|
"prevId": "ad43c733-01c3-4841-b600-252421350fb9",
|
||||||
"version": "7",
|
"version": "7",
|
||||||
"dialect": "postgresql",
|
"dialect": "postgresql",
|
||||||
"tables": {
|
"tables": {
|
||||||
@@ -241,43 +241,6 @@
|
|||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": false
|
"notNull": false
|
||||||
},
|
},
|
||||||
"giteaProjectId": {
|
|
||||||
"name": "giteaProjectId",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"giteaRepository": {
|
|
||||||
"name": "giteaRepository",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"giteaOwner": {
|
|
||||||
"name": "giteaOwner",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"giteaBranch": {
|
|
||||||
"name": "giteaBranch",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"giteaBuildPath": {
|
|
||||||
"name": "giteaBuildPath",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"default": "'/'"
|
|
||||||
},
|
|
||||||
"giteaPathNamespace": {
|
|
||||||
"name": "giteaPathNamespace",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"bitbucketRepository": {
|
"bitbucketRepository": {
|
||||||
"name": "bitbucketRepository",
|
"name": "bitbucketRepository",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -489,12 +452,6 @@
|
|||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": false
|
"notNull": false
|
||||||
},
|
},
|
||||||
"giteaId": {
|
|
||||||
"name": "giteaId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"bitbucketId": {
|
"bitbucketId": {
|
||||||
"name": "bitbucketId",
|
"name": "bitbucketId",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -575,19 +532,6 @@
|
|||||||
"onDelete": "set null",
|
"onDelete": "set null",
|
||||||
"onUpdate": "no action"
|
"onUpdate": "no action"
|
||||||
},
|
},
|
||||||
"application_giteaId_gitea_giteaId_fk": {
|
|
||||||
"name": "application_giteaId_gitea_giteaId_fk",
|
|
||||||
"tableFrom": "application",
|
|
||||||
"tableTo": "gitea",
|
|
||||||
"columnsFrom": [
|
|
||||||
"giteaId"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"giteaId"
|
|
||||||
],
|
|
||||||
"onDelete": "set null",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
},
|
|
||||||
"application_bitbucketId_bitbucket_bitbucketId_fk": {
|
"application_bitbucketId_bitbucket_bitbucketId_fk": {
|
||||||
"name": "application_bitbucketId_bitbucket_bitbucketId_fk",
|
"name": "application_bitbucketId_bitbucket_bitbucketId_fk",
|
||||||
"tableFrom": "application",
|
"tableFrom": "application",
|
||||||
@@ -923,13 +867,6 @@
|
|||||||
"notNull": true,
|
"notNull": true,
|
||||||
"default": false
|
"default": false
|
||||||
},
|
},
|
||||||
"enableLogRotation": {
|
|
||||||
"name": "enableLogRotation",
|
|
||||||
"type": "boolean",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"default": false
|
|
||||||
},
|
|
||||||
"logCleanupCron": {
|
"logCleanupCron": {
|
||||||
"name": "logCleanupCron",
|
"name": "logCleanupCron",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -3988,88 +3925,6 @@
|
|||||||
"checkConstraints": {},
|
"checkConstraints": {},
|
||||||
"isRLSEnabled": false
|
"isRLSEnabled": false
|
||||||
},
|
},
|
||||||
"public.gitea": {
|
|
||||||
"name": "gitea",
|
|
||||||
"schema": "",
|
|
||||||
"columns": {
|
|
||||||
"giteaId": {
|
|
||||||
"name": "giteaId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"giteaUrl": {
|
|
||||||
"name": "giteaUrl",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"default": "'https://gitea.com'"
|
|
||||||
},
|
|
||||||
"redirect_uri": {
|
|
||||||
"name": "redirect_uri",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"client_id": {
|
|
||||||
"name": "client_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"client_secret": {
|
|
||||||
"name": "client_secret",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"gitProviderId": {
|
|
||||||
"name": "gitProviderId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"gitea_username": {
|
|
||||||
"name": "gitea_username",
|
|
||||||
"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
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {
|
|
||||||
"gitea_gitProviderId_git_provider_gitProviderId_fk": {
|
|
||||||
"name": "gitea_gitProviderId_git_provider_gitProviderId_fk",
|
|
||||||
"tableFrom": "gitea",
|
|
||||||
"tableTo": "git_provider",
|
|
||||||
"columnsFrom": [
|
|
||||||
"gitProviderId"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"gitProviderId"
|
|
||||||
],
|
|
||||||
"onDelete": "cascade",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {},
|
|
||||||
"policies": {},
|
|
||||||
"checkConstraints": {},
|
|
||||||
"isRLSEnabled": false
|
|
||||||
},
|
|
||||||
"public.server": {
|
"public.server": {
|
||||||
"name": "server",
|
"name": "server",
|
||||||
"schema": "",
|
"schema": "",
|
||||||
@@ -5134,7 +4989,6 @@
|
|||||||
"github",
|
"github",
|
||||||
"gitlab",
|
"gitlab",
|
||||||
"bitbucket",
|
"bitbucket",
|
||||||
"gitea",
|
|
||||||
"drop"
|
"drop"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -5259,8 +5113,7 @@
|
|||||||
"values": [
|
"values": [
|
||||||
"github",
|
"github",
|
||||||
"gitlab",
|
"gitlab",
|
||||||
"bitbucket",
|
"bitbucket"
|
||||||
"gitea"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"public.serverStatus": {
|
"public.serverStatus": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"id": "85133e87-6886-493f-89d6-c83162f76d50",
|
"id": "3584a243-55f6-418b-aece-985d878b30d7",
|
||||||
"prevId": "8946105c-e69c-49c7-8334-784ee2419a92",
|
"prevId": "5808aed9-4223-4ac4-ae22-6c0dae500d75",
|
||||||
"version": "7",
|
"version": "7",
|
||||||
"dialect": "postgresql",
|
"dialect": "postgresql",
|
||||||
"tables": {
|
"tables": {
|
||||||
@@ -241,43 +241,6 @@
|
|||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": false
|
"notNull": false
|
||||||
},
|
},
|
||||||
"giteaProjectId": {
|
|
||||||
"name": "giteaProjectId",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"giteaRepository": {
|
|
||||||
"name": "giteaRepository",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"giteaOwner": {
|
|
||||||
"name": "giteaOwner",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"giteaBranch": {
|
|
||||||
"name": "giteaBranch",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"giteaBuildPath": {
|
|
||||||
"name": "giteaBuildPath",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"default": "'/'"
|
|
||||||
},
|
|
||||||
"giteaPathNamespace": {
|
|
||||||
"name": "giteaPathNamespace",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"bitbucketRepository": {
|
"bitbucketRepository": {
|
||||||
"name": "bitbucketRepository",
|
"name": "bitbucketRepository",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -489,12 +452,6 @@
|
|||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": false
|
"notNull": false
|
||||||
},
|
},
|
||||||
"giteaId": {
|
|
||||||
"name": "giteaId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"bitbucketId": {
|
"bitbucketId": {
|
||||||
"name": "bitbucketId",
|
"name": "bitbucketId",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -575,19 +532,6 @@
|
|||||||
"onDelete": "set null",
|
"onDelete": "set null",
|
||||||
"onUpdate": "no action"
|
"onUpdate": "no action"
|
||||||
},
|
},
|
||||||
"application_giteaId_gitea_giteaId_fk": {
|
|
||||||
"name": "application_giteaId_gitea_giteaId_fk",
|
|
||||||
"tableFrom": "application",
|
|
||||||
"tableTo": "gitea",
|
|
||||||
"columnsFrom": [
|
|
||||||
"giteaId"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"giteaId"
|
|
||||||
],
|
|
||||||
"onDelete": "set null",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
},
|
|
||||||
"application_bitbucketId_bitbucket_bitbucketId_fk": {
|
"application_bitbucketId_bitbucket_bitbucketId_fk": {
|
||||||
"name": "application_bitbucketId_bitbucket_bitbucketId_fk",
|
"name": "application_bitbucketId_bitbucket_bitbucketId_fk",
|
||||||
"tableFrom": "application",
|
"tableFrom": "application",
|
||||||
@@ -923,13 +867,6 @@
|
|||||||
"notNull": true,
|
"notNull": true,
|
||||||
"default": false
|
"default": false
|
||||||
},
|
},
|
||||||
"enableLogRotation": {
|
|
||||||
"name": "enableLogRotation",
|
|
||||||
"type": "boolean",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"default": false
|
|
||||||
},
|
|
||||||
"logCleanupCron": {
|
"logCleanupCron": {
|
||||||
"name": "logCleanupCron",
|
"name": "logCleanupCron",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -3988,112 +3925,6 @@
|
|||||||
"checkConstraints": {},
|
"checkConstraints": {},
|
||||||
"isRLSEnabled": false
|
"isRLSEnabled": false
|
||||||
},
|
},
|
||||||
"public.gitea": {
|
|
||||||
"name": "gitea",
|
|
||||||
"schema": "",
|
|
||||||
"columns": {
|
|
||||||
"giteaId": {
|
|
||||||
"name": "giteaId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"giteaUrl": {
|
|
||||||
"name": "giteaUrl",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"default": "'https://gitea.com'"
|
|
||||||
},
|
|
||||||
"redirect_uri": {
|
|
||||||
"name": "redirect_uri",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"client_id": {
|
|
||||||
"name": "client_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"client_secret": {
|
|
||||||
"name": "client_secret",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"gitProviderId": {
|
|
||||||
"name": "gitProviderId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"gitea_username": {
|
|
||||||
"name": "gitea_username",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"access_token": {
|
|
||||||
"name": "access_token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"refresh_token": {
|
|
||||||
"name": "refresh_token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"expires_at": {
|
|
||||||
"name": "expires_at",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"organization_name": {
|
|
||||||
"name": "organization_name",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"scopes": {
|
|
||||||
"name": "scopes",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"last_authenticated_at": {
|
|
||||||
"name": "last_authenticated_at",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {
|
|
||||||
"gitea_gitProviderId_git_provider_gitProviderId_fk": {
|
|
||||||
"name": "gitea_gitProviderId_git_provider_gitProviderId_fk",
|
|
||||||
"tableFrom": "gitea",
|
|
||||||
"tableTo": "git_provider",
|
|
||||||
"columnsFrom": [
|
|
||||||
"gitProviderId"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"gitProviderId"
|
|
||||||
],
|
|
||||||
"onDelete": "cascade",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {},
|
|
||||||
"policies": {},
|
|
||||||
"checkConstraints": {},
|
|
||||||
"isRLSEnabled": false
|
|
||||||
},
|
|
||||||
"public.server": {
|
"public.server": {
|
||||||
"name": "server",
|
"name": "server",
|
||||||
"schema": "",
|
"schema": "",
|
||||||
@@ -5158,7 +4989,6 @@
|
|||||||
"github",
|
"github",
|
||||||
"gitlab",
|
"gitlab",
|
||||||
"bitbucket",
|
"bitbucket",
|
||||||
"gitea",
|
|
||||||
"drop"
|
"drop"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -5283,8 +5113,7 @@
|
|||||||
"values": [
|
"values": [
|
||||||
"github",
|
"github",
|
||||||
"gitlab",
|
"gitlab",
|
||||||
"bitbucket",
|
"bitbucket"
|
||||||
"gitea"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"public.serverStatus": {
|
"public.serverStatus": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"id": "00d7b47b-5341-4dda-b121-4a87cec39d95",
|
"id": "dd51ff04-a160-4d0d-b72f-4916493b740f",
|
||||||
"prevId": "85133e87-6886-493f-89d6-c83162f76d50",
|
"prevId": "3584a243-55f6-418b-aece-985d878b30d7",
|
||||||
"version": "7",
|
"version": "7",
|
||||||
"dialect": "postgresql",
|
"dialect": "postgresql",
|
||||||
"tables": {
|
"tables": {
|
||||||
@@ -247,43 +247,6 @@
|
|||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": false
|
"notNull": false
|
||||||
},
|
},
|
||||||
"giteaProjectId": {
|
|
||||||
"name": "giteaProjectId",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"giteaRepository": {
|
|
||||||
"name": "giteaRepository",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"giteaOwner": {
|
|
||||||
"name": "giteaOwner",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"giteaBranch": {
|
|
||||||
"name": "giteaBranch",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"giteaBuildPath": {
|
|
||||||
"name": "giteaBuildPath",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"default": "'/'"
|
|
||||||
},
|
|
||||||
"giteaPathNamespace": {
|
|
||||||
"name": "giteaPathNamespace",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"bitbucketRepository": {
|
"bitbucketRepository": {
|
||||||
"name": "bitbucketRepository",
|
"name": "bitbucketRepository",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -495,12 +458,6 @@
|
|||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": false
|
"notNull": false
|
||||||
},
|
},
|
||||||
"giteaId": {
|
|
||||||
"name": "giteaId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"bitbucketId": {
|
"bitbucketId": {
|
||||||
"name": "bitbucketId",
|
"name": "bitbucketId",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -581,19 +538,6 @@
|
|||||||
"onDelete": "set null",
|
"onDelete": "set null",
|
||||||
"onUpdate": "no action"
|
"onUpdate": "no action"
|
||||||
},
|
},
|
||||||
"application_giteaId_gitea_giteaId_fk": {
|
|
||||||
"name": "application_giteaId_gitea_giteaId_fk",
|
|
||||||
"tableFrom": "application",
|
|
||||||
"tableTo": "gitea",
|
|
||||||
"columnsFrom": [
|
|
||||||
"giteaId"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"giteaId"
|
|
||||||
],
|
|
||||||
"onDelete": "set null",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
},
|
|
||||||
"application_bitbucketId_bitbucket_bitbucketId_fk": {
|
"application_bitbucketId_bitbucket_bitbucketId_fk": {
|
||||||
"name": "application_bitbucketId_bitbucket_bitbucketId_fk",
|
"name": "application_bitbucketId_bitbucket_bitbucketId_fk",
|
||||||
"tableFrom": "application",
|
"tableFrom": "application",
|
||||||
@@ -929,13 +873,6 @@
|
|||||||
"notNull": true,
|
"notNull": true,
|
||||||
"default": false
|
"default": false
|
||||||
},
|
},
|
||||||
"enableLogRotation": {
|
|
||||||
"name": "enableLogRotation",
|
|
||||||
"type": "boolean",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"default": false
|
|
||||||
},
|
|
||||||
"logCleanupCron": {
|
"logCleanupCron": {
|
||||||
"name": "logCleanupCron",
|
"name": "logCleanupCron",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -2971,24 +2908,6 @@
|
|||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": false
|
"notNull": false
|
||||||
},
|
},
|
||||||
"giteaRepository": {
|
|
||||||
"name": "giteaRepository",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"giteaOwner": {
|
|
||||||
"name": "giteaOwner",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"giteaBranch": {
|
|
||||||
"name": "giteaBranch",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"customGitUrl": {
|
"customGitUrl": {
|
||||||
"name": "customGitUrl",
|
"name": "customGitUrl",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -3080,12 +2999,6 @@
|
|||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": false
|
"notNull": false
|
||||||
},
|
},
|
||||||
"giteaId": {
|
|
||||||
"name": "giteaId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"serverId": {
|
"serverId": {
|
||||||
"name": "serverId",
|
"name": "serverId",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -3160,19 +3073,6 @@
|
|||||||
"onDelete": "set null",
|
"onDelete": "set null",
|
||||||
"onUpdate": "no action"
|
"onUpdate": "no action"
|
||||||
},
|
},
|
||||||
"compose_giteaId_gitea_giteaId_fk": {
|
|
||||||
"name": "compose_giteaId_gitea_giteaId_fk",
|
|
||||||
"tableFrom": "compose",
|
|
||||||
"tableTo": "gitea",
|
|
||||||
"columnsFrom": [
|
|
||||||
"giteaId"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"giteaId"
|
|
||||||
],
|
|
||||||
"onDelete": "set null",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
},
|
|
||||||
"compose_serverId_server_serverId_fk": {
|
"compose_serverId_server_serverId_fk": {
|
||||||
"name": "compose_serverId_server_serverId_fk",
|
"name": "compose_serverId_server_serverId_fk",
|
||||||
"tableFrom": "compose",
|
"tableFrom": "compose",
|
||||||
@@ -4031,112 +3931,6 @@
|
|||||||
"checkConstraints": {},
|
"checkConstraints": {},
|
||||||
"isRLSEnabled": false
|
"isRLSEnabled": false
|
||||||
},
|
},
|
||||||
"public.gitea": {
|
|
||||||
"name": "gitea",
|
|
||||||
"schema": "",
|
|
||||||
"columns": {
|
|
||||||
"giteaId": {
|
|
||||||
"name": "giteaId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"giteaUrl": {
|
|
||||||
"name": "giteaUrl",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"default": "'https://gitea.com'"
|
|
||||||
},
|
|
||||||
"redirect_uri": {
|
|
||||||
"name": "redirect_uri",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"client_id": {
|
|
||||||
"name": "client_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"client_secret": {
|
|
||||||
"name": "client_secret",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"gitProviderId": {
|
|
||||||
"name": "gitProviderId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"gitea_username": {
|
|
||||||
"name": "gitea_username",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"access_token": {
|
|
||||||
"name": "access_token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"refresh_token": {
|
|
||||||
"name": "refresh_token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"expires_at": {
|
|
||||||
"name": "expires_at",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"organization_name": {
|
|
||||||
"name": "organization_name",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"scopes": {
|
|
||||||
"name": "scopes",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"last_authenticated_at": {
|
|
||||||
"name": "last_authenticated_at",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {
|
|
||||||
"gitea_gitProviderId_git_provider_gitProviderId_fk": {
|
|
||||||
"name": "gitea_gitProviderId_git_provider_gitProviderId_fk",
|
|
||||||
"tableFrom": "gitea",
|
|
||||||
"tableTo": "git_provider",
|
|
||||||
"columnsFrom": [
|
|
||||||
"gitProviderId"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"gitProviderId"
|
|
||||||
],
|
|
||||||
"onDelete": "cascade",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {},
|
|
||||||
"policies": {},
|
|
||||||
"checkConstraints": {},
|
|
||||||
"isRLSEnabled": false
|
|
||||||
},
|
|
||||||
"public.server": {
|
"public.server": {
|
||||||
"name": "server",
|
"name": "server",
|
||||||
"schema": "",
|
"schema": "",
|
||||||
@@ -5201,7 +4995,6 @@
|
|||||||
"github",
|
"github",
|
||||||
"gitlab",
|
"gitlab",
|
||||||
"bitbucket",
|
"bitbucket",
|
||||||
"gitea",
|
|
||||||
"drop"
|
"drop"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -5298,7 +5091,6 @@
|
|||||||
"github",
|
"github",
|
||||||
"gitlab",
|
"gitlab",
|
||||||
"bitbucket",
|
"bitbucket",
|
||||||
"gitea",
|
|
||||||
"raw"
|
"raw"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -5327,8 +5119,7 @@
|
|||||||
"values": [
|
"values": [
|
||||||
"github",
|
"github",
|
||||||
"gitlab",
|
"gitlab",
|
||||||
"bitbucket",
|
"bitbucket"
|
||||||
"gitea"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"public.serverStatus": {
|
"public.serverStatus": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"id": "7c8508ba-01eb-487e-88cf-0abe10916904",
|
"id": "27ba0f3d-859f-4233-a179-8aee11ad9179",
|
||||||
"prevId": "f74127dc-3cda-4091-988f-97b60eb22427",
|
"prevId": "dd51ff04-a160-4d0d-b72f-4916493b740f",
|
||||||
"version": "7",
|
"version": "7",
|
||||||
"dialect": "postgresql",
|
"dialect": "postgresql",
|
||||||
"tables": {
|
"tables": {
|
||||||
@@ -179,13 +179,6 @@
|
|||||||
"notNull": true,
|
"notNull": true,
|
||||||
"default": "'github'"
|
"default": "'github'"
|
||||||
},
|
},
|
||||||
"cleanCache": {
|
|
||||||
"name": "cleanCache",
|
|
||||||
"type": "boolean",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"default": false
|
|
||||||
},
|
|
||||||
"repository": {
|
"repository": {
|
||||||
"name": "repository",
|
"name": "repository",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -254,43 +247,6 @@
|
|||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": false
|
"notNull": false
|
||||||
},
|
},
|
||||||
"giteaProjectId": {
|
|
||||||
"name": "giteaProjectId",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"giteaRepository": {
|
|
||||||
"name": "giteaRepository",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"giteaOwner": {
|
|
||||||
"name": "giteaOwner",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"giteaBranch": {
|
|
||||||
"name": "giteaBranch",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"giteaBuildPath": {
|
|
||||||
"name": "giteaBuildPath",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"default": "'/'"
|
|
||||||
},
|
|
||||||
"giteaPathNamespace": {
|
|
||||||
"name": "giteaPathNamespace",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"bitbucketRepository": {
|
"bitbucketRepository": {
|
||||||
"name": "bitbucketRepository",
|
"name": "bitbucketRepository",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -502,12 +458,6 @@
|
|||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": false
|
"notNull": false
|
||||||
},
|
},
|
||||||
"giteaId": {
|
|
||||||
"name": "giteaId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"bitbucketId": {
|
"bitbucketId": {
|
||||||
"name": "bitbucketId",
|
"name": "bitbucketId",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -588,19 +538,6 @@
|
|||||||
"onDelete": "set null",
|
"onDelete": "set null",
|
||||||
"onUpdate": "no action"
|
"onUpdate": "no action"
|
||||||
},
|
},
|
||||||
"application_giteaId_gitea_giteaId_fk": {
|
|
||||||
"name": "application_giteaId_gitea_giteaId_fk",
|
|
||||||
"tableFrom": "application",
|
|
||||||
"tableTo": "gitea",
|
|
||||||
"columnsFrom": [
|
|
||||||
"giteaId"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"giteaId"
|
|
||||||
],
|
|
||||||
"onDelete": "set null",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
},
|
|
||||||
"application_bitbucketId_bitbucket_bitbucketId_fk": {
|
"application_bitbucketId_bitbucket_bitbucketId_fk": {
|
||||||
"name": "application_bitbucketId_bitbucket_bitbucketId_fk",
|
"name": "application_bitbucketId_bitbucket_bitbucketId_fk",
|
||||||
"tableFrom": "application",
|
"tableFrom": "application",
|
||||||
@@ -1766,12 +1703,6 @@
|
|||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": true
|
"notNull": true
|
||||||
},
|
},
|
||||||
"keepLatestCount": {
|
|
||||||
"name": "keepLatestCount",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"databaseType": {
|
"databaseType": {
|
||||||
"name": "databaseType",
|
"name": "databaseType",
|
||||||
"type": "databaseType",
|
"type": "databaseType",
|
||||||
@@ -2977,24 +2908,6 @@
|
|||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": false
|
"notNull": false
|
||||||
},
|
},
|
||||||
"giteaRepository": {
|
|
||||||
"name": "giteaRepository",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"giteaOwner": {
|
|
||||||
"name": "giteaOwner",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"giteaBranch": {
|
|
||||||
"name": "giteaBranch",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"customGitUrl": {
|
"customGitUrl": {
|
||||||
"name": "customGitUrl",
|
"name": "customGitUrl",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -3092,12 +3005,6 @@
|
|||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": false
|
"notNull": false
|
||||||
},
|
},
|
||||||
"giteaId": {
|
|
||||||
"name": "giteaId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"serverId": {
|
"serverId": {
|
||||||
"name": "serverId",
|
"name": "serverId",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -3172,19 +3079,6 @@
|
|||||||
"onDelete": "set null",
|
"onDelete": "set null",
|
||||||
"onUpdate": "no action"
|
"onUpdate": "no action"
|
||||||
},
|
},
|
||||||
"compose_giteaId_gitea_giteaId_fk": {
|
|
||||||
"name": "compose_giteaId_gitea_giteaId_fk",
|
|
||||||
"tableFrom": "compose",
|
|
||||||
"tableTo": "gitea",
|
|
||||||
"columnsFrom": [
|
|
||||||
"giteaId"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"giteaId"
|
|
||||||
],
|
|
||||||
"onDelete": "set null",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
},
|
|
||||||
"compose_serverId_server_serverId_fk": {
|
"compose_serverId_server_serverId_fk": {
|
||||||
"name": "compose_serverId_server_serverId_fk",
|
"name": "compose_serverId_server_serverId_fk",
|
||||||
"tableFrom": "compose",
|
"tableFrom": "compose",
|
||||||
@@ -4043,107 +3937,6 @@
|
|||||||
"checkConstraints": {},
|
"checkConstraints": {},
|
||||||
"isRLSEnabled": false
|
"isRLSEnabled": false
|
||||||
},
|
},
|
||||||
"public.gitea": {
|
|
||||||
"name": "gitea",
|
|
||||||
"schema": "",
|
|
||||||
"columns": {
|
|
||||||
"giteaId": {
|
|
||||||
"name": "giteaId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"giteaUrl": {
|
|
||||||
"name": "giteaUrl",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"default": "'https://gitea.com'"
|
|
||||||
},
|
|
||||||
"redirect_uri": {
|
|
||||||
"name": "redirect_uri",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"client_id": {
|
|
||||||
"name": "client_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"client_secret": {
|
|
||||||
"name": "client_secret",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"gitProviderId": {
|
|
||||||
"name": "gitProviderId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"gitea_username": {
|
|
||||||
"name": "gitea_username",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"access_token": {
|
|
||||||
"name": "access_token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"refresh_token": {
|
|
||||||
"name": "refresh_token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"expires_at": {
|
|
||||||
"name": "expires_at",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"scopes": {
|
|
||||||
"name": "scopes",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"default": "'repo,repo:status,read:user,read:org'"
|
|
||||||
},
|
|
||||||
"last_authenticated_at": {
|
|
||||||
"name": "last_authenticated_at",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {
|
|
||||||
"gitea_gitProviderId_git_provider_gitProviderId_fk": {
|
|
||||||
"name": "gitea_gitProviderId_git_provider_gitProviderId_fk",
|
|
||||||
"tableFrom": "gitea",
|
|
||||||
"tableTo": "git_provider",
|
|
||||||
"columnsFrom": [
|
|
||||||
"gitProviderId"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"gitProviderId"
|
|
||||||
],
|
|
||||||
"onDelete": "cascade",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {},
|
|
||||||
"policies": {},
|
|
||||||
"checkConstraints": {},
|
|
||||||
"isRLSEnabled": false
|
|
||||||
},
|
|
||||||
"public.server": {
|
"public.server": {
|
||||||
"name": "server",
|
"name": "server",
|
||||||
"schema": "",
|
"schema": "",
|
||||||
@@ -5208,7 +5001,6 @@
|
|||||||
"github",
|
"github",
|
||||||
"gitlab",
|
"gitlab",
|
||||||
"bitbucket",
|
"bitbucket",
|
||||||
"gitea",
|
|
||||||
"drop"
|
"drop"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -5305,7 +5097,6 @@
|
|||||||
"github",
|
"github",
|
||||||
"gitlab",
|
"gitlab",
|
||||||
"bitbucket",
|
"bitbucket",
|
||||||
"gitea",
|
|
||||||
"raw"
|
"raw"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -5334,8 +5125,7 @@
|
|||||||
"values": [
|
"values": [
|
||||||
"github",
|
"github",
|
||||||
"gitlab",
|
"gitlab",
|
||||||
"bitbucket",
|
"bitbucket"
|
||||||
"gitea"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"public.serverStatus": {
|
"public.serverStatus": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"id": "c8f3ee9b-66c6-4a23-a151-78e04363bdf9",
|
"id": "d4d95ab9-16bd-4583-949e-d6ae0a0bb7a0",
|
||||||
"prevId": "f74127dc-3cda-4091-988f-97b60eb22427",
|
"prevId": "27ba0f3d-859f-4233-a179-8aee11ad9179",
|
||||||
"version": "7",
|
"version": "7",
|
||||||
"dialect": "postgresql",
|
"dialect": "postgresql",
|
||||||
"tables": {
|
"tables": {
|
||||||
@@ -179,13 +179,6 @@
|
|||||||
"notNull": true,
|
"notNull": true,
|
||||||
"default": "'github'"
|
"default": "'github'"
|
||||||
},
|
},
|
||||||
"cleanCache": {
|
|
||||||
"name": "cleanCache",
|
|
||||||
"type": "boolean",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"default": false
|
|
||||||
},
|
|
||||||
"repository": {
|
"repository": {
|
||||||
"name": "repository",
|
"name": "repository",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -254,43 +247,6 @@
|
|||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": false
|
"notNull": false
|
||||||
},
|
},
|
||||||
"giteaProjectId": {
|
|
||||||
"name": "giteaProjectId",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"giteaRepository": {
|
|
||||||
"name": "giteaRepository",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"giteaOwner": {
|
|
||||||
"name": "giteaOwner",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"giteaBranch": {
|
|
||||||
"name": "giteaBranch",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"giteaBuildPath": {
|
|
||||||
"name": "giteaBuildPath",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"default": "'/'"
|
|
||||||
},
|
|
||||||
"giteaPathNamespace": {
|
|
||||||
"name": "giteaPathNamespace",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"bitbucketRepository": {
|
"bitbucketRepository": {
|
||||||
"name": "bitbucketRepository",
|
"name": "bitbucketRepository",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -502,12 +458,6 @@
|
|||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": false
|
"notNull": false
|
||||||
},
|
},
|
||||||
"giteaId": {
|
|
||||||
"name": "giteaId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"bitbucketId": {
|
"bitbucketId": {
|
||||||
"name": "bitbucketId",
|
"name": "bitbucketId",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -588,19 +538,6 @@
|
|||||||
"onDelete": "set null",
|
"onDelete": "set null",
|
||||||
"onUpdate": "no action"
|
"onUpdate": "no action"
|
||||||
},
|
},
|
||||||
"application_giteaId_gitea_giteaId_fk": {
|
|
||||||
"name": "application_giteaId_gitea_giteaId_fk",
|
|
||||||
"tableFrom": "application",
|
|
||||||
"tableTo": "gitea",
|
|
||||||
"columnsFrom": [
|
|
||||||
"giteaId"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"giteaId"
|
|
||||||
],
|
|
||||||
"onDelete": "set null",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
},
|
|
||||||
"application_bitbucketId_bitbucket_bitbucketId_fk": {
|
"application_bitbucketId_bitbucket_bitbucketId_fk": {
|
||||||
"name": "application_bitbucketId_bitbucket_bitbucketId_fk",
|
"name": "application_bitbucketId_bitbucket_bitbucketId_fk",
|
||||||
"tableFrom": "application",
|
"tableFrom": "application",
|
||||||
@@ -2977,24 +2914,6 @@
|
|||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": false
|
"notNull": false
|
||||||
},
|
},
|
||||||
"giteaRepository": {
|
|
||||||
"name": "giteaRepository",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"giteaOwner": {
|
|
||||||
"name": "giteaOwner",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"giteaBranch": {
|
|
||||||
"name": "giteaBranch",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"customGitUrl": {
|
"customGitUrl": {
|
||||||
"name": "customGitUrl",
|
"name": "customGitUrl",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -3092,12 +3011,6 @@
|
|||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": false
|
"notNull": false
|
||||||
},
|
},
|
||||||
"giteaId": {
|
|
||||||
"name": "giteaId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"serverId": {
|
"serverId": {
|
||||||
"name": "serverId",
|
"name": "serverId",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -3172,19 +3085,6 @@
|
|||||||
"onDelete": "set null",
|
"onDelete": "set null",
|
||||||
"onUpdate": "no action"
|
"onUpdate": "no action"
|
||||||
},
|
},
|
||||||
"compose_giteaId_gitea_giteaId_fk": {
|
|
||||||
"name": "compose_giteaId_gitea_giteaId_fk",
|
|
||||||
"tableFrom": "compose",
|
|
||||||
"tableTo": "gitea",
|
|
||||||
"columnsFrom": [
|
|
||||||
"giteaId"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"giteaId"
|
|
||||||
],
|
|
||||||
"onDelete": "set null",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
},
|
|
||||||
"compose_serverId_server_serverId_fk": {
|
"compose_serverId_server_serverId_fk": {
|
||||||
"name": "compose_serverId_server_serverId_fk",
|
"name": "compose_serverId_server_serverId_fk",
|
||||||
"tableFrom": "compose",
|
"tableFrom": "compose",
|
||||||
@@ -4043,107 +3943,6 @@
|
|||||||
"checkConstraints": {},
|
"checkConstraints": {},
|
||||||
"isRLSEnabled": false
|
"isRLSEnabled": false
|
||||||
},
|
},
|
||||||
"public.gitea": {
|
|
||||||
"name": "gitea",
|
|
||||||
"schema": "",
|
|
||||||
"columns": {
|
|
||||||
"giteaId": {
|
|
||||||
"name": "giteaId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"giteaUrl": {
|
|
||||||
"name": "giteaUrl",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"default": "'https://gitea.com'"
|
|
||||||
},
|
|
||||||
"redirect_uri": {
|
|
||||||
"name": "redirect_uri",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"client_id": {
|
|
||||||
"name": "client_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"client_secret": {
|
|
||||||
"name": "client_secret",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"gitProviderId": {
|
|
||||||
"name": "gitProviderId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"gitea_username": {
|
|
||||||
"name": "gitea_username",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"access_token": {
|
|
||||||
"name": "access_token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"refresh_token": {
|
|
||||||
"name": "refresh_token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"expires_at": {
|
|
||||||
"name": "expires_at",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"scopes": {
|
|
||||||
"name": "scopes",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"default": "'repo,repo:status,read:user,read:org'"
|
|
||||||
},
|
|
||||||
"last_authenticated_at": {
|
|
||||||
"name": "last_authenticated_at",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {
|
|
||||||
"gitea_gitProviderId_git_provider_gitProviderId_fk": {
|
|
||||||
"name": "gitea_gitProviderId_git_provider_gitProviderId_fk",
|
|
||||||
"tableFrom": "gitea",
|
|
||||||
"tableTo": "git_provider",
|
|
||||||
"columnsFrom": [
|
|
||||||
"gitProviderId"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"gitProviderId"
|
|
||||||
],
|
|
||||||
"onDelete": "cascade",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {},
|
|
||||||
"policies": {},
|
|
||||||
"checkConstraints": {},
|
|
||||||
"isRLSEnabled": false
|
|
||||||
},
|
|
||||||
"public.server": {
|
"public.server": {
|
||||||
"name": "server",
|
"name": "server",
|
||||||
"schema": "",
|
"schema": "",
|
||||||
@@ -5208,7 +5007,6 @@
|
|||||||
"github",
|
"github",
|
||||||
"gitlab",
|
"gitlab",
|
||||||
"bitbucket",
|
"bitbucket",
|
||||||
"gitea",
|
|
||||||
"drop"
|
"drop"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -5305,7 +5103,6 @@
|
|||||||
"github",
|
"github",
|
||||||
"gitlab",
|
"gitlab",
|
||||||
"bitbucket",
|
"bitbucket",
|
||||||
"gitea",
|
|
||||||
"raw"
|
"raw"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -5334,8 +5131,7 @@
|
|||||||
"values": [
|
"values": [
|
||||||
"github",
|
"github",
|
||||||
"gitlab",
|
"gitlab",
|
||||||
"bitbucket",
|
"bitbucket"
|
||||||
"gitea"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"public.serverStatus": {
|
"public.serverStatus": {
|
||||||
|
|||||||
5360
apps/dokploy/drizzle/meta/0079_snapshot.json
Normal file
5360
apps/dokploy/drizzle/meta/0079_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -502,64 +502,64 @@
|
|||||||
{
|
{
|
||||||
"idx": 71,
|
"idx": 71,
|
||||||
"version": "7",
|
"version": "7",
|
||||||
"when": 1741559743256,
|
"when": 1741460060541,
|
||||||
"tag": "0071_flimsy_plazm",
|
"tag": "0071_flaky_black_queen",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idx": 72,
|
"idx": 72,
|
||||||
"version": "7",
|
"version": "7",
|
||||||
"when": 1741593124105,
|
"when": 1741487009559,
|
||||||
"tag": "0072_low_redwing",
|
"tag": "0072_green_susan_delgado",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idx": 73,
|
"idx": 73,
|
||||||
"version": "7",
|
"version": "7",
|
||||||
"when": 1741645208694,
|
"when": 1741489681190,
|
||||||
"tag": "0073_dark_tigra",
|
"tag": "0073_hot_domino",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idx": 74,
|
"idx": 74,
|
||||||
"version": "7",
|
"version": "7",
|
||||||
"when": 1741673569715,
|
"when": 1741490064139,
|
||||||
"tag": "0074_military_miss_america",
|
"tag": "0074_black_quasar",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idx": 75,
|
"idx": 75,
|
||||||
"version": "7",
|
"version": "7",
|
||||||
"when": 1742018928109,
|
"when": 1741491527516,
|
||||||
"tag": "0075_wild_xorn",
|
"tag": "0075_young_typhoid_mary",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idx": 76,
|
"idx": 76,
|
||||||
"version": "7",
|
"version": "7",
|
||||||
"when": 1742237840762,
|
"when": 1741493754270,
|
||||||
"tag": "0076_tough_iron_patriot",
|
"tag": "0076_young_sharon_ventura",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idx": 77,
|
"idx": 77,
|
||||||
"version": "7",
|
"version": "7",
|
||||||
"when": 1742241730000,
|
"when": 1741510086231,
|
||||||
"tag": "0076_young_sharon_ventura",
|
"tag": "0077_chemical_dreadnoughts",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idx": 78,
|
"idx": 78,
|
||||||
"version": "7",
|
"version": "7",
|
||||||
"when": 1742241730001,
|
"when": 1742112194375,
|
||||||
"tag": "0077_chemical_dreadnoughts",
|
"tag": "0078_uneven_omega_sentinel",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idx": 79,
|
"idx": 79,
|
||||||
"version": "7",
|
"version": "7",
|
||||||
"when": 17422417300002,
|
"when": 1742281690186,
|
||||||
"tag": "0078_uneven_omega_sentinel",
|
"tag": "0079_bizarre_wendell_rand",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "dokploy",
|
"name": "dokploy",
|
||||||
"version": "v0.20.4",
|
"version": "v0.20.7",
|
||||||
"private": true,
|
"private": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ export default async function handler(
|
|||||||
try {
|
try {
|
||||||
const branchName = githubBody?.ref?.replace("refs/heads/", "");
|
const branchName = githubBody?.ref?.replace("refs/heads/", "");
|
||||||
const repository = githubBody?.repository?.name;
|
const repository = githubBody?.repository?.name;
|
||||||
|
|
||||||
const deploymentTitle = extractCommitMessage(req.headers, req.body);
|
const deploymentTitle = extractCommitMessage(req.headers, req.body);
|
||||||
const deploymentHash = extractHash(req.headers, req.body);
|
const deploymentHash = extractHash(req.headers, req.body);
|
||||||
const owner = githubBody?.repository?.owner?.name;
|
const owner = githubBody?.repository?.owner?.name;
|
||||||
@@ -107,6 +108,7 @@ export default async function handler(
|
|||||||
eq(applications.branch, branchName),
|
eq(applications.branch, branchName),
|
||||||
eq(applications.repository, repository),
|
eq(applications.repository, repository),
|
||||||
eq(applications.owner, owner),
|
eq(applications.owner, owner),
|
||||||
|
eq(applications.githubId, githubResult.githubId),
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -151,6 +153,7 @@ export default async function handler(
|
|||||||
eq(compose.branch, branchName),
|
eq(compose.branch, branchName),
|
||||||
eq(compose.repository, repository),
|
eq(compose.repository, repository),
|
||||||
eq(compose.owner, owner),
|
eq(compose.owner, owner),
|
||||||
|
eq(compose.githubId, githubResult.githubId),
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -240,6 +243,7 @@ export default async function handler(
|
|||||||
eq(applications.branch, branch),
|
eq(applications.branch, branch),
|
||||||
eq(applications.isPreviewDeploymentsActive, true),
|
eq(applications.isPreviewDeploymentsActive, true),
|
||||||
eq(applications.owner, owner),
|
eq(applications.owner, owner),
|
||||||
|
eq(applications.githubId, githubResult.githubId),
|
||||||
),
|
),
|
||||||
with: {
|
with: {
|
||||||
previewDeployments: true,
|
previewDeployments: true,
|
||||||
|
|||||||
@@ -11,9 +11,13 @@ import {
|
|||||||
createBackup,
|
createBackup,
|
||||||
findBackupById,
|
findBackupById,
|
||||||
findMariadbByBackupId,
|
findMariadbByBackupId,
|
||||||
|
findMariadbById,
|
||||||
findMongoByBackupId,
|
findMongoByBackupId,
|
||||||
|
findMongoById,
|
||||||
findMySqlByBackupId,
|
findMySqlByBackupId,
|
||||||
|
findMySqlById,
|
||||||
findPostgresByBackupId,
|
findPostgresByBackupId,
|
||||||
|
findPostgresById,
|
||||||
findServerById,
|
findServerById,
|
||||||
removeBackupById,
|
removeBackupById,
|
||||||
removeScheduleBackup,
|
removeScheduleBackup,
|
||||||
@@ -25,7 +29,21 @@ import {
|
|||||||
updateBackupById,
|
updateBackupById,
|
||||||
} from "@dokploy/server";
|
} from "@dokploy/server";
|
||||||
|
|
||||||
|
import { findDestinationById } from "@dokploy/server/services/destination";
|
||||||
|
import { getS3Credentials } from "@dokploy/server/utils/backups/utils";
|
||||||
|
import {
|
||||||
|
execAsync,
|
||||||
|
execAsyncRemote,
|
||||||
|
} from "@dokploy/server/utils/process/execAsync";
|
||||||
|
import {
|
||||||
|
restoreMariadbBackup,
|
||||||
|
restoreMongoBackup,
|
||||||
|
restoreMySqlBackup,
|
||||||
|
restorePostgresBackup,
|
||||||
|
} from "@dokploy/server/utils/restore";
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
|
import { observable } from "@trpc/server/observable";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
export const backupRouter = createTRPCRouter({
|
export const backupRouter = createTRPCRouter({
|
||||||
create: protectedProcedure
|
create: protectedProcedure
|
||||||
@@ -209,27 +227,146 @@ export const backupRouter = createTRPCRouter({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
listBackupFiles: protectedProcedure
|
||||||
|
.input(
|
||||||
|
z.object({
|
||||||
|
destinationId: z.string(),
|
||||||
|
search: z.string(),
|
||||||
|
serverId: z.string().optional(),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.query(async ({ input }) => {
|
||||||
|
try {
|
||||||
|
const destination = await findDestinationById(input.destinationId);
|
||||||
|
const rcloneFlags = getS3Credentials(destination);
|
||||||
|
const bucketPath = `:s3:${destination.bucket}`;
|
||||||
|
|
||||||
|
const lastSlashIndex = input.search.lastIndexOf("/");
|
||||||
|
const baseDir =
|
||||||
|
lastSlashIndex !== -1
|
||||||
|
? input.search.slice(0, lastSlashIndex + 1)
|
||||||
|
: "";
|
||||||
|
const searchTerm =
|
||||||
|
lastSlashIndex !== -1
|
||||||
|
? input.search.slice(lastSlashIndex + 1)
|
||||||
|
: input.search;
|
||||||
|
|
||||||
|
const searchPath = baseDir ? `${bucketPath}/${baseDir}` : bucketPath;
|
||||||
|
const listCommand = `rclone lsf ${rcloneFlags.join(" ")} "${searchPath}" | head -n 100`;
|
||||||
|
|
||||||
|
let stdout = "";
|
||||||
|
|
||||||
|
if (input.serverId) {
|
||||||
|
const result = await execAsyncRemote(listCommand, input.serverId);
|
||||||
|
stdout = result.stdout;
|
||||||
|
} else {
|
||||||
|
const result = await execAsync(listCommand);
|
||||||
|
stdout = result.stdout;
|
||||||
|
}
|
||||||
|
|
||||||
|
const files = stdout.split("\n").filter(Boolean);
|
||||||
|
|
||||||
|
const results = baseDir
|
||||||
|
? files.map((file) => `${baseDir}${file}`)
|
||||||
|
: files;
|
||||||
|
|
||||||
|
if (searchTerm) {
|
||||||
|
return results.filter((file) =>
|
||||||
|
file.toLowerCase().includes(searchTerm.toLowerCase()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
} catch (error) {
|
||||||
|
throw new TRPCError({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message:
|
||||||
|
error instanceof Error
|
||||||
|
? error.message
|
||||||
|
: "Error listing backup files",
|
||||||
|
cause: error,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
restoreBackupWithLogs: protectedProcedure
|
||||||
|
.meta({
|
||||||
|
openapi: {
|
||||||
|
enabled: false,
|
||||||
|
path: "/restore-backup-with-logs",
|
||||||
|
method: "POST",
|
||||||
|
override: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.input(
|
||||||
|
z.object({
|
||||||
|
databaseId: z.string(),
|
||||||
|
databaseType: z.enum(["postgres", "mysql", "mariadb", "mongo"]),
|
||||||
|
databaseName: z.string().min(1),
|
||||||
|
backupFile: z.string().min(1),
|
||||||
|
destinationId: z.string().min(1),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.subscription(async ({ input }) => {
|
||||||
|
const destination = await findDestinationById(input.destinationId);
|
||||||
|
if (input.databaseType === "postgres") {
|
||||||
|
const postgres = await findPostgresById(input.databaseId);
|
||||||
|
|
||||||
|
return observable<string>((emit) => {
|
||||||
|
restorePostgresBackup(
|
||||||
|
postgres,
|
||||||
|
destination,
|
||||||
|
input.databaseName,
|
||||||
|
input.backupFile,
|
||||||
|
(log) => {
|
||||||
|
emit.next(log);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (input.databaseType === "mysql") {
|
||||||
|
const mysql = await findMySqlById(input.databaseId);
|
||||||
|
return observable<string>((emit) => {
|
||||||
|
restoreMySqlBackup(
|
||||||
|
mysql,
|
||||||
|
destination,
|
||||||
|
input.databaseName,
|
||||||
|
input.backupFile,
|
||||||
|
(log) => {
|
||||||
|
emit.next(log);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (input.databaseType === "mariadb") {
|
||||||
|
const mariadb = await findMariadbById(input.databaseId);
|
||||||
|
return observable<string>((emit) => {
|
||||||
|
restoreMariadbBackup(
|
||||||
|
mariadb,
|
||||||
|
destination,
|
||||||
|
input.databaseName,
|
||||||
|
input.backupFile,
|
||||||
|
(log) => {
|
||||||
|
emit.next(log);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (input.databaseType === "mongo") {
|
||||||
|
const mongo = await findMongoById(input.databaseId);
|
||||||
|
return observable<string>((emit) => {
|
||||||
|
restoreMongoBackup(
|
||||||
|
mongo,
|
||||||
|
destination,
|
||||||
|
input.databaseName,
|
||||||
|
input.backupFile,
|
||||||
|
(log) => {
|
||||||
|
emit.next(log);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
// export const getAdminId = async (backupId: string) => {
|
|
||||||
// const backup = await findBackupById(backupId);
|
|
||||||
|
|
||||||
// if (backup.databaseType === "postgres" && backup.postgresId) {
|
|
||||||
// const postgres = await findPostgresById(backup.postgresId);
|
|
||||||
// return postgres.project.adminId;
|
|
||||||
// }
|
|
||||||
// if (backup.databaseType === "mariadb" && backup.mariadbId) {
|
|
||||||
// const mariadb = await findMariadbById(backup.mariadbId);
|
|
||||||
// return mariadb.project.adminId;
|
|
||||||
// }
|
|
||||||
// if (backup.databaseType === "mysql" && backup.mysqlId) {
|
|
||||||
// const mysql = await findMySqlById(backup.mysqlId);
|
|
||||||
// return mysql.project.adminId;
|
|
||||||
// }
|
|
||||||
// if (backup.databaseType === "mongo" && backup.mongoId) {
|
|
||||||
// const mongo = await findMongoById(backup.mongoId);
|
|
||||||
// return mongo.project.adminId;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return null;
|
|
||||||
// };
|
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ import {
|
|||||||
findDomainById,
|
findDomainById,
|
||||||
findDomainsByApplicationId,
|
findDomainsByApplicationId,
|
||||||
findDomainsByComposeId,
|
findDomainsByComposeId,
|
||||||
|
findOrganizationById,
|
||||||
findPreviewDeploymentById,
|
findPreviewDeploymentById,
|
||||||
|
findServerById,
|
||||||
generateTraefikMeDomain,
|
generateTraefikMeDomain,
|
||||||
manageDomain,
|
manageDomain,
|
||||||
removeDomain,
|
removeDomain,
|
||||||
@@ -94,6 +96,19 @@ export const domainRouter = createTRPCRouter({
|
|||||||
input.serverId,
|
input.serverId,
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
canGenerateTraefikMeDomains: protectedProcedure
|
||||||
|
.input(z.object({ serverId: z.string() }))
|
||||||
|
.query(async ({ input, ctx }) => {
|
||||||
|
const organization = await findOrganizationById(
|
||||||
|
ctx.session.activeOrganizationId,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (input.serverId) {
|
||||||
|
const server = await findServerById(input.serverId);
|
||||||
|
return server.ipAddress;
|
||||||
|
}
|
||||||
|
return organization?.owner.serverIp;
|
||||||
|
}),
|
||||||
|
|
||||||
update: protectedProcedure
|
update: protectedProcedure
|
||||||
.input(apiUpdateDomain)
|
.input(apiUpdateDomain)
|
||||||
|
|||||||
@@ -2,12 +2,16 @@ import type { IncomingMessage } from "node:http";
|
|||||||
import * as bcrypt from "bcrypt";
|
import * as bcrypt from "bcrypt";
|
||||||
import { betterAuth } from "better-auth";
|
import { betterAuth } from "better-auth";
|
||||||
import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
||||||
|
import { APIError } from "better-auth/api";
|
||||||
import { apiKey, organization, twoFactor } from "better-auth/plugins";
|
import { apiKey, organization, twoFactor } from "better-auth/plugins";
|
||||||
import { and, desc, eq } from "drizzle-orm";
|
import { and, desc, eq } from "drizzle-orm";
|
||||||
import { IS_CLOUD } from "../constants";
|
import { IS_CLOUD } from "../constants";
|
||||||
import { db } from "../db";
|
import { db } from "../db";
|
||||||
import * as schema from "../db/schema";
|
import * as schema from "../db/schema";
|
||||||
|
import { getUserByToken } from "../services/admin";
|
||||||
|
import { updateUser } from "../services/user";
|
||||||
import { sendEmail } from "../verification/send-verification-email";
|
import { sendEmail } from "../verification/send-verification-email";
|
||||||
|
import { getPublicIpWithFallback } from "../wss/utils";
|
||||||
|
|
||||||
const { handler, api } = betterAuth({
|
const { handler, api } = betterAuth({
|
||||||
database: drizzleAdapter(db, {
|
database: drizzleAdapter(db, {
|
||||||
@@ -88,11 +92,40 @@ const { handler, api } = betterAuth({
|
|||||||
databaseHooks: {
|
databaseHooks: {
|
||||||
user: {
|
user: {
|
||||||
create: {
|
create: {
|
||||||
|
before: async (_user, context) => {
|
||||||
|
if (!IS_CLOUD) {
|
||||||
|
const xDokployToken =
|
||||||
|
context?.request?.headers?.get("x-dokploy-token");
|
||||||
|
if (xDokployToken) {
|
||||||
|
const user = await getUserByToken(xDokployToken);
|
||||||
|
if (!user) {
|
||||||
|
throw new APIError("BAD_REQUEST", {
|
||||||
|
message: "User not found",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const isAdminPresent = await db.query.member.findFirst({
|
||||||
|
where: eq(schema.member.role, "owner"),
|
||||||
|
});
|
||||||
|
if (isAdminPresent) {
|
||||||
|
throw new APIError("BAD_REQUEST", {
|
||||||
|
message: "Admin is already created",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
after: async (user) => {
|
after: async (user) => {
|
||||||
const isAdminPresent = await db.query.member.findFirst({
|
const isAdminPresent = await db.query.member.findFirst({
|
||||||
where: eq(schema.member.role, "owner"),
|
where: eq(schema.member.role, "owner"),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!IS_CLOUD) {
|
||||||
|
await updateUser(user.id, {
|
||||||
|
serverIp: await getPublicIpWithFallback(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (IS_CLOUD || !isAdminPresent) {
|
if (IS_CLOUD || !isAdminPresent) {
|
||||||
await db.transaction(async (tx) => {
|
await db.transaction(async (tx) => {
|
||||||
const organization = await tx
|
const organization = await tx
|
||||||
|
|||||||
@@ -361,7 +361,7 @@ const installUtilities = () => `
|
|||||||
alpine)
|
alpine)
|
||||||
sed -i '/^#.*\/community/s/^#//' /etc/apk/repositories
|
sed -i '/^#.*\/community/s/^#//' /etc/apk/repositories
|
||||||
apk update >/dev/null
|
apk update >/dev/null
|
||||||
apk add curl wget git jq openssl >/dev/null
|
apk add curl wget git jq openssl sudo unzip tar >/dev/null
|
||||||
;;
|
;;
|
||||||
ubuntu | debian | raspbian)
|
ubuntu | debian | raspbian)
|
||||||
DEBIAN_FRONTEND=noninteractive apt-get update -y >/dev/null
|
DEBIAN_FRONTEND=noninteractive apt-get update -y >/dev/null
|
||||||
|
|||||||
@@ -101,11 +101,11 @@ export const initializeTraefik = async ({
|
|||||||
console.log("Waiting for service cleanup...");
|
console.log("Waiting for service cleanup...");
|
||||||
await new Promise((resolve) => setTimeout(resolve, 5000));
|
await new Promise((resolve) => setTimeout(resolve, 5000));
|
||||||
attempts++;
|
attempts++;
|
||||||
} catch (e) {
|
} catch (_e) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (_err) {
|
||||||
console.log("No existing service to remove");
|
console.log("No existing service to remove");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,7 +120,7 @@ export const initializeTraefik = async ({
|
|||||||
|
|
||||||
await container.remove({ force: true });
|
await container.remove({ force: true });
|
||||||
await new Promise((resolve) => setTimeout(resolve, 5000));
|
await new Promise((resolve) => setTimeout(resolve, 5000));
|
||||||
} catch (error) {
|
} catch (_err) {
|
||||||
console.log("No existing container to remove");
|
console.log("No existing container to remove");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
4
packages/server/src/utils/restore/index.ts
Normal file
4
packages/server/src/utils/restore/index.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export { restorePostgresBackup } from "./postgres";
|
||||||
|
export { restoreMySqlBackup } from "./mysql";
|
||||||
|
export { restoreMariadbBackup } from "./mariadb";
|
||||||
|
export { restoreMongoBackup } from "./mongo";
|
||||||
56
packages/server/src/utils/restore/mariadb.ts
Normal file
56
packages/server/src/utils/restore/mariadb.ts
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import type { Destination } from "@dokploy/server/services/destination";
|
||||||
|
import type { Mariadb } from "@dokploy/server/services/mariadb";
|
||||||
|
import { getS3Credentials } from "../backups/utils";
|
||||||
|
import {
|
||||||
|
getRemoteServiceContainer,
|
||||||
|
getServiceContainer,
|
||||||
|
} from "../docker/utils";
|
||||||
|
import { execAsync, execAsyncRemote } from "../process/execAsync";
|
||||||
|
|
||||||
|
export const restoreMariadbBackup = async (
|
||||||
|
mariadb: Mariadb,
|
||||||
|
destination: Destination,
|
||||||
|
database: string,
|
||||||
|
backupFile: string,
|
||||||
|
emit: (log: string) => void,
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
const { appName, databasePassword, databaseUser, serverId } = mariadb;
|
||||||
|
|
||||||
|
const rcloneFlags = getS3Credentials(destination);
|
||||||
|
const bucketPath = `:s3:${destination.bucket}`;
|
||||||
|
const backupPath = `${bucketPath}/${backupFile}`;
|
||||||
|
|
||||||
|
const { Id: containerName } = serverId
|
||||||
|
? await getRemoteServiceContainer(serverId, appName)
|
||||||
|
: await getServiceContainer(appName);
|
||||||
|
|
||||||
|
const restoreCommand = `
|
||||||
|
rclone cat ${rcloneFlags.join(" ")} "${backupPath}" | gunzip | docker exec -i ${containerName} mariadb -u ${databaseUser} -p${databasePassword} ${database}
|
||||||
|
`;
|
||||||
|
|
||||||
|
emit("Starting restore...");
|
||||||
|
|
||||||
|
emit(`Executing command: ${restoreCommand}`);
|
||||||
|
|
||||||
|
if (serverId) {
|
||||||
|
await execAsyncRemote(serverId, restoreCommand);
|
||||||
|
} else {
|
||||||
|
await execAsync(restoreCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit("Restore completed successfully!");
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
emit(
|
||||||
|
`Error: ${
|
||||||
|
error instanceof Error
|
||||||
|
? error.message
|
||||||
|
: "Error restoring mariadb backup"
|
||||||
|
}`,
|
||||||
|
);
|
||||||
|
throw new Error(
|
||||||
|
error instanceof Error ? error.message : "Error restoring mariadb backup",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
64
packages/server/src/utils/restore/mongo.ts
Normal file
64
packages/server/src/utils/restore/mongo.ts
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import type { Destination } from "@dokploy/server/services/destination";
|
||||||
|
import type { Mongo } from "@dokploy/server/services/mongo";
|
||||||
|
import { getS3Credentials } from "../backups/utils";
|
||||||
|
import {
|
||||||
|
getRemoteServiceContainer,
|
||||||
|
getServiceContainer,
|
||||||
|
} from "../docker/utils";
|
||||||
|
import { execAsync, execAsyncRemote } from "../process/execAsync";
|
||||||
|
|
||||||
|
export const restoreMongoBackup = async (
|
||||||
|
mongo: Mongo,
|
||||||
|
destination: Destination,
|
||||||
|
database: string,
|
||||||
|
backupFile: string,
|
||||||
|
emit: (log: string) => void,
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
const { appName, databasePassword, databaseUser, serverId } = mongo;
|
||||||
|
|
||||||
|
const rcloneFlags = getS3Credentials(destination);
|
||||||
|
const bucketPath = `:s3:${destination.bucket}`;
|
||||||
|
const backupPath = `${bucketPath}/${backupFile}`;
|
||||||
|
|
||||||
|
const { Id: containerName } = serverId
|
||||||
|
? await getRemoteServiceContainer(serverId, appName)
|
||||||
|
: await getServiceContainer(appName);
|
||||||
|
|
||||||
|
// For MongoDB, we need to first download the backup file since mongorestore expects a directory
|
||||||
|
const tempDir = "/tmp/dokploy-restore";
|
||||||
|
const fileName = backupFile.split("/").pop() || "backup.dump.gz";
|
||||||
|
const decompressedName = fileName.replace(".gz", "");
|
||||||
|
|
||||||
|
const downloadCommand = `\
|
||||||
|
rm -rf ${tempDir} && \
|
||||||
|
mkdir -p ${tempDir} && \
|
||||||
|
rclone copy ${rcloneFlags.join(" ")} "${backupPath}" ${tempDir} && \
|
||||||
|
cd ${tempDir} && \
|
||||||
|
gunzip -f "${fileName}" && \
|
||||||
|
docker exec -i ${containerName} mongorestore --username ${databaseUser} --password ${databasePassword} --authenticationDatabase admin --db ${database} --archive < "${decompressedName}" && \
|
||||||
|
rm -rf ${tempDir}`;
|
||||||
|
|
||||||
|
emit("Starting restore...");
|
||||||
|
|
||||||
|
emit(`Executing command: ${downloadCommand}`);
|
||||||
|
|
||||||
|
if (serverId) {
|
||||||
|
await execAsyncRemote(serverId, downloadCommand);
|
||||||
|
} else {
|
||||||
|
await execAsync(downloadCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit("Restore completed successfully!");
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
emit(
|
||||||
|
`Error: ${
|
||||||
|
error instanceof Error ? error.message : "Error restoring mongo backup"
|
||||||
|
}`,
|
||||||
|
);
|
||||||
|
throw new Error(
|
||||||
|
error instanceof Error ? error.message : "Error restoring mongo backup",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
54
packages/server/src/utils/restore/mysql.ts
Normal file
54
packages/server/src/utils/restore/mysql.ts
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import type { Destination } from "@dokploy/server/services/destination";
|
||||||
|
import type { MySql } from "@dokploy/server/services/mysql";
|
||||||
|
import { getS3Credentials } from "../backups/utils";
|
||||||
|
import {
|
||||||
|
getRemoteServiceContainer,
|
||||||
|
getServiceContainer,
|
||||||
|
} from "../docker/utils";
|
||||||
|
import { execAsync, execAsyncRemote } from "../process/execAsync";
|
||||||
|
|
||||||
|
export const restoreMySqlBackup = async (
|
||||||
|
mysql: MySql,
|
||||||
|
destination: Destination,
|
||||||
|
database: string,
|
||||||
|
backupFile: string,
|
||||||
|
emit: (log: string) => void,
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
const { appName, databaseRootPassword, serverId } = mysql;
|
||||||
|
|
||||||
|
const rcloneFlags = getS3Credentials(destination);
|
||||||
|
const bucketPath = `:s3:${destination.bucket}`;
|
||||||
|
const backupPath = `${bucketPath}/${backupFile}`;
|
||||||
|
|
||||||
|
const { Id: containerName } = serverId
|
||||||
|
? await getRemoteServiceContainer(serverId, appName)
|
||||||
|
: await getServiceContainer(appName);
|
||||||
|
|
||||||
|
const restoreCommand = `
|
||||||
|
rclone cat ${rcloneFlags.join(" ")} "${backupPath}" | gunzip | docker exec -i ${containerName} mysql -u root -p${databaseRootPassword} ${database}
|
||||||
|
`;
|
||||||
|
|
||||||
|
emit("Starting restore...");
|
||||||
|
|
||||||
|
emit(`Executing command: ${restoreCommand}`);
|
||||||
|
|
||||||
|
if (serverId) {
|
||||||
|
await execAsyncRemote(serverId, restoreCommand);
|
||||||
|
} else {
|
||||||
|
await execAsync(restoreCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit("Restore completed successfully!");
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
emit(
|
||||||
|
`Error: ${
|
||||||
|
error instanceof Error ? error.message : "Error restoring mysql backup"
|
||||||
|
}`,
|
||||||
|
);
|
||||||
|
throw new Error(
|
||||||
|
error instanceof Error ? error.message : "Error restoring mysql backup",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
60
packages/server/src/utils/restore/postgres.ts
Normal file
60
packages/server/src/utils/restore/postgres.ts
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import type { Destination } from "@dokploy/server/services/destination";
|
||||||
|
import type { Postgres } from "@dokploy/server/services/postgres";
|
||||||
|
import { getS3Credentials } from "../backups/utils";
|
||||||
|
import {
|
||||||
|
getRemoteServiceContainer,
|
||||||
|
getServiceContainer,
|
||||||
|
} from "../docker/utils";
|
||||||
|
import { execAsync, execAsyncRemote } from "../process/execAsync";
|
||||||
|
|
||||||
|
export const restorePostgresBackup = async (
|
||||||
|
postgres: Postgres,
|
||||||
|
destination: Destination,
|
||||||
|
database: string,
|
||||||
|
backupFile: string,
|
||||||
|
emit: (log: string) => void,
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
const { appName, databaseUser, serverId } = postgres;
|
||||||
|
|
||||||
|
const rcloneFlags = getS3Credentials(destination);
|
||||||
|
const bucketPath = `:s3:${destination.bucket}`;
|
||||||
|
|
||||||
|
const backupPath = `${bucketPath}/${backupFile}`;
|
||||||
|
|
||||||
|
const { Id: containerName } = serverId
|
||||||
|
? await getRemoteServiceContainer(serverId, appName)
|
||||||
|
: await getServiceContainer(appName);
|
||||||
|
|
||||||
|
emit("Starting restore...");
|
||||||
|
emit(`Backup path: ${backupPath}`);
|
||||||
|
|
||||||
|
const command = `\
|
||||||
|
rclone cat ${rcloneFlags.join(" ")} "${backupPath}" | gunzip | docker exec -i ${containerName} pg_restore -U ${databaseUser} -d ${database} --clean --if-exists`;
|
||||||
|
|
||||||
|
emit(`Executing command: ${command}`);
|
||||||
|
|
||||||
|
if (serverId) {
|
||||||
|
const { stdout, stderr } = await execAsyncRemote(serverId, command);
|
||||||
|
emit(stdout);
|
||||||
|
emit(stderr);
|
||||||
|
} else {
|
||||||
|
const { stdout, stderr } = await execAsync(command);
|
||||||
|
console.log("stdout", stdout);
|
||||||
|
console.log("stderr", stderr);
|
||||||
|
emit(stdout);
|
||||||
|
emit(stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit("Restore completed successfully!");
|
||||||
|
} catch (error) {
|
||||||
|
emit(
|
||||||
|
`Error: ${
|
||||||
|
error instanceof Error
|
||||||
|
? error.message
|
||||||
|
: "Error restoring postgres backup"
|
||||||
|
}`,
|
||||||
|
);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user