mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
feat(gitea): add Gitea repository support
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import type { Schema } from "@dokploy/server/templates";
|
||||||
import type { CompleteTemplate } from "@dokploy/server/templates/processors";
|
import type { CompleteTemplate } from "@dokploy/server/templates/processors";
|
||||||
import { processTemplate } from "@dokploy/server/templates/processors";
|
import { processTemplate } from "@dokploy/server/templates/processors";
|
||||||
import type { Schema } from "@dokploy/server/templates";
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
describe("processTemplate", () => {
|
describe("processTemplate", () => {
|
||||||
// Mock schema for testing
|
// Mock schema for testing
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { AlertBlock } from "@/components/shared/alert-block";
|
||||||
import { CodeEditor } from "@/components/shared/code-editor";
|
import { CodeEditor } from "@/components/shared/code-editor";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import {
|
import {
|
||||||
@@ -32,7 +33,6 @@ 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";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { AlertBlock } from "@/components/shared/alert-block";
|
|
||||||
|
|
||||||
const ImportSchema = z.object({
|
const ImportSchema = z.object({
|
||||||
base64: z.string(),
|
base64: z.string(),
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import { Form } from "@/components/ui/form";
|
|||||||
import { Secrets } from "@/components/ui/secrets";
|
import { Secrets } from "@/components/ui/secrets";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import { useEffect } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { useEffect } from "react";
|
|
||||||
|
|
||||||
const addEnvironmentSchema = z.object({
|
const addEnvironmentSchema = z.object({
|
||||||
env: z.string(),
|
env: z.string(),
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
import { BitbucketIcon } from "@/components/icons/data-tools-icons";
|
||||||
import { AlertBlock } from "@/components/shared/alert-block";
|
import { AlertBlock } from "@/components/shared/alert-block";
|
||||||
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import {
|
import {
|
||||||
Command,
|
Command,
|
||||||
@@ -39,13 +41,11 @@ import { cn } from "@/lib/utils";
|
|||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { CheckIcon, ChevronsUpDown, X } from "lucide-react";
|
import { CheckIcon, ChevronsUpDown, X } from "lucide-react";
|
||||||
|
import Link from "next/link";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { Badge } from "@/components/ui/badge";
|
|
||||||
import { BitbucketIcon } from "@/components/icons/data-tools-icons";
|
|
||||||
import Link from "next/link";
|
|
||||||
|
|
||||||
const BitbucketProviderSchema = z.object({
|
const BitbucketProviderSchema = z.object({
|
||||||
buildPath: z.string().min(1, "Path is required").default("/"),
|
buildPath: z.string().min(1, "Path is required").default("/"),
|
||||||
|
|||||||
@@ -115,7 +115,11 @@ export const SaveDockerProvider = ({ applicationId }: Props) => {
|
|||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Username</FormLabel>
|
<FormLabel>Username</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="Username" autoComplete="username" {...field} />
|
<Input
|
||||||
|
placeholder="Username"
|
||||||
|
autoComplete="username"
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
@@ -130,7 +134,12 @@ export const SaveDockerProvider = ({ applicationId }: Props) => {
|
|||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Password</FormLabel>
|
<FormLabel>Password</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="Password" autoComplete="one-time-code" {...field} type="password" />
|
<Input
|
||||||
|
placeholder="Password"
|
||||||
|
autoComplete="one-time-code"
|
||||||
|
{...field}
|
||||||
|
type="password"
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
|||||||
@@ -26,15 +26,15 @@ import {
|
|||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { KeyRoundIcon, LockIcon, X } from "lucide-react";
|
import { KeyRoundIcon, LockIcon, X } from "lucide-react";
|
||||||
import { useRouter } from "next/router";
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
|
import { GitIcon } from "@/components/icons/data-tools-icons";
|
||||||
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { Badge } from "@/components/ui/badge";
|
|
||||||
import { GitIcon } from "@/components/icons/data-tools-icons";
|
|
||||||
|
|
||||||
const GitProviderSchema = z.object({
|
const GitProviderSchema = z.object({
|
||||||
buildPath: z.string().min(1, "Path is required").default("/"),
|
buildPath: z.string().min(1, "Path is required").default("/"),
|
||||||
|
|||||||
@@ -235,7 +235,8 @@ export const SaveGiteaProvider = ({ applicationId }: Props) => {
|
|||||||
? "Loading...."
|
? "Loading...."
|
||||||
: field.value.owner
|
: field.value.owner
|
||||||
? repositories?.find(
|
? repositories?.find(
|
||||||
(repo: GiteaRepository) => repo.name === field.value.repo,
|
(repo: GiteaRepository) =>
|
||||||
|
repo.name === field.value.repo,
|
||||||
)?.name
|
)?.name
|
||||||
: "Select repository"}
|
: "Select repository"}
|
||||||
|
|
||||||
@@ -327,7 +328,8 @@ export const SaveGiteaProvider = ({ applicationId }: Props) => {
|
|||||||
? "Loading...."
|
? "Loading...."
|
||||||
: field.value
|
: field.value
|
||||||
? branches?.find(
|
? branches?.find(
|
||||||
(branch: GiteaBranch) => branch.name === field.value,
|
(branch: GiteaBranch) =>
|
||||||
|
branch.name === field.value,
|
||||||
)?.name
|
)?.name
|
||||||
: "Select branch"}
|
: "Select branch"}
|
||||||
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { GithubIcon } from "@/components/icons/data-tools-icons";
|
||||||
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import {
|
import {
|
||||||
Command,
|
Command,
|
||||||
@@ -34,17 +36,15 @@ import {
|
|||||||
TooltipProvider,
|
TooltipProvider,
|
||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from "@/components/ui/tooltip";
|
} from "@/components/ui/tooltip";
|
||||||
import { Badge } from "@/components/ui/badge";
|
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { CheckIcon, ChevronsUpDown, HelpCircle, Plus, X } from "lucide-react";
|
import { CheckIcon, ChevronsUpDown, HelpCircle, Plus, X } from "lucide-react";
|
||||||
|
import Link from "next/link";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import Link from "next/link";
|
|
||||||
import { GithubIcon } from "@/components/icons/data-tools-icons";
|
|
||||||
|
|
||||||
const GithubProviderSchema = z.object({
|
const GithubProviderSchema = z.object({
|
||||||
buildPath: z.string().min(1, "Path is required").default("/"),
|
buildPath: z.string().min(1, "Path is required").default("/"),
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
import { GitlabIcon } from "@/components/icons/data-tools-icons";
|
||||||
import { AlertBlock } from "@/components/shared/alert-block";
|
import { AlertBlock } from "@/components/shared/alert-block";
|
||||||
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import {
|
import {
|
||||||
Command,
|
Command,
|
||||||
@@ -35,17 +37,15 @@ import {
|
|||||||
TooltipProvider,
|
TooltipProvider,
|
||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from "@/components/ui/tooltip";
|
} from "@/components/ui/tooltip";
|
||||||
import { Badge } from "@/components/ui/badge";
|
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { CheckIcon, ChevronsUpDown, HelpCircle, Plus, X } from "lucide-react";
|
import { CheckIcon, ChevronsUpDown, HelpCircle, Plus, X } from "lucide-react";
|
||||||
|
import Link from "next/link";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import Link from "next/link";
|
|
||||||
import { GitlabIcon } from "@/components/icons/data-tools-icons";
|
|
||||||
|
|
||||||
const GitlabProviderSchema = z.object({
|
const GitlabProviderSchema = z.object({
|
||||||
buildPath: z.string().min(1, "Path is required").default("/"),
|
buildPath: z.string().min(1, "Path is required").default("/"),
|
||||||
|
|||||||
@@ -20,7 +20,14 @@ import { SaveBitbucketProvider } from "./save-bitbucket-provider";
|
|||||||
import { SaveDragNDrop } from "./save-drag-n-drop";
|
import { SaveDragNDrop } from "./save-drag-n-drop";
|
||||||
import { SaveGitlabProvider } from "./save-gitlab-provider";
|
import { SaveGitlabProvider } from "./save-gitlab-provider";
|
||||||
|
|
||||||
type TabState = "github" | "docker" | "git" | "drop" | "gitlab" | "bitbucket" | "gitea";
|
type TabState =
|
||||||
|
| "github"
|
||||||
|
| "docker"
|
||||||
|
| "git"
|
||||||
|
| "drop"
|
||||||
|
| "gitlab"
|
||||||
|
| "bitbucket"
|
||||||
|
| "gitea";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
applicationId: string;
|
applicationId: string;
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import {
|
|||||||
TooltipProvider,
|
TooltipProvider,
|
||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from "@/components/ui/tooltip";
|
} from "@/components/ui/tooltip";
|
||||||
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
|
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
||||||
import {
|
import {
|
||||||
Ban,
|
Ban,
|
||||||
CheckCircle2,
|
CheckCircle2,
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import {
|
|||||||
TooltipProvider,
|
TooltipProvider,
|
||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from "@/components/ui/tooltip";
|
} from "@/components/ui/tooltip";
|
||||||
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
|
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
||||||
import { Ban, CheckCircle2, Hammer, HelpCircle, 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";
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
import { BitbucketIcon } from "@/components/icons/data-tools-icons";
|
||||||
import { AlertBlock } from "@/components/shared/alert-block";
|
import { AlertBlock } from "@/components/shared/alert-block";
|
||||||
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import {
|
import {
|
||||||
Command,
|
Command,
|
||||||
@@ -39,13 +41,11 @@ import { cn } from "@/lib/utils";
|
|||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { CheckIcon, ChevronsUpDown, X } from "lucide-react";
|
import { CheckIcon, ChevronsUpDown, X } from "lucide-react";
|
||||||
|
import Link from "next/link";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { Badge } from "@/components/ui/badge";
|
|
||||||
import { BitbucketIcon } from "@/components/icons/data-tools-icons";
|
|
||||||
import Link from "next/link";
|
|
||||||
|
|
||||||
const BitbucketProviderSchema = z.object({
|
const BitbucketProviderSchema = z.object({
|
||||||
composePath: z.string().min(1),
|
composePath: z.string().min(1),
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { GitIcon } from "@/components/icons/data-tools-icons";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import {
|
import {
|
||||||
@@ -27,13 +28,12 @@ import {
|
|||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { KeyRoundIcon, LockIcon, X } from "lucide-react";
|
import { KeyRoundIcon, LockIcon, X } from "lucide-react";
|
||||||
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { GitIcon } from "@/components/icons/data-tools-icons";
|
|
||||||
import Link from "next/link";
|
|
||||||
|
|
||||||
const GitProviderSchema = z.object({
|
const GitProviderSchema = z.object({
|
||||||
composePath: z.string().min(1),
|
composePath: z.string().min(1),
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { GithubIcon } from "@/components/icons/data-tools-icons";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import {
|
import {
|
||||||
@@ -39,12 +40,11 @@ import { cn } from "@/lib/utils";
|
|||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { CheckIcon, ChevronsUpDown, X } from "lucide-react";
|
import { CheckIcon, ChevronsUpDown, X } from "lucide-react";
|
||||||
|
import Link from "next/link";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { GithubIcon } from "@/components/icons/data-tools-icons";
|
|
||||||
import Link from "next/link";
|
|
||||||
|
|
||||||
const GithubProviderSchema = z.object({
|
const GithubProviderSchema = z.object({
|
||||||
composePath: z.string().min(1),
|
composePath: z.string().min(1),
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
import { GitlabIcon } from "@/components/icons/data-tools-icons";
|
||||||
import { AlertBlock } from "@/components/shared/alert-block";
|
import { AlertBlock } from "@/components/shared/alert-block";
|
||||||
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import {
|
import {
|
||||||
Command,
|
Command,
|
||||||
@@ -39,13 +41,11 @@ import { cn } from "@/lib/utils";
|
|||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { CheckIcon, ChevronsUpDown, X } from "lucide-react";
|
import { CheckIcon, ChevronsUpDown, X } from "lucide-react";
|
||||||
|
import Link from "next/link";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { Badge } from "@/components/ui/badge";
|
|
||||||
import { GitlabIcon } from "@/components/icons/data-tools-icons";
|
|
||||||
import Link from "next/link";
|
|
||||||
|
|
||||||
const GitlabProviderSchema = z.object({
|
const GitlabProviderSchema = z.object({
|
||||||
composePath: z.string().min(1),
|
composePath: z.string().min(1),
|
||||||
|
|||||||
@@ -147,7 +147,9 @@ export const IsolatedDeployment = ({ composeId }: Props) => {
|
|||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="mt-4 flex flex-row items-center justify-between rounded-lg border p-3 shadow-sm">
|
<FormItem className="mt-4 flex flex-row items-center justify-between rounded-lg border p-3 shadow-sm">
|
||||||
<div className="space-y-0.5">
|
<div className="space-y-0.5">
|
||||||
<FormLabel>Enable Isolated Deployment ({data?.appName})</FormLabel>
|
<FormLabel>
|
||||||
|
Enable Isolated Deployment ({data?.appName})
|
||||||
|
</FormLabel>
|
||||||
<FormDescription>
|
<FormDescription>
|
||||||
Enable isolated deployment to the compose file.
|
Enable isolated deployment to the compose file.
|
||||||
</FormDescription>
|
</FormDescription>
|
||||||
|
|||||||
@@ -286,10 +286,15 @@ export const AddBackup = ({ databaseId, databaseType, refetch }: Props) => {
|
|||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Keep the latest</FormLabel>
|
<FormLabel>Keep the latest</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input type="number" placeholder={"keeps all the backups if left empty"} {...field} />
|
<Input
|
||||||
|
type="number"
|
||||||
|
placeholder={"keeps all the backups if left empty"}
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormDescription>
|
<FormDescription>
|
||||||
Optional. If provided, only keeps the latest N backups in the cloud.
|
Optional. If provided, only keeps the latest N backups
|
||||||
|
in the cloud.
|
||||||
</FormDescription>
|
</FormDescription>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
|||||||
@@ -16,18 +16,20 @@ import {
|
|||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { DatabaseBackup, Play, Trash2 } from "lucide-react";
|
import { DatabaseBackup, Play, Trash2 } from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
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 { UpdateBackup } from "./update-backup";
|
import { UpdateBackup } from "./update-backup";
|
||||||
import { useState } from "react";
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
id: string;
|
id: string;
|
||||||
type: Exclude<ServiceType, "application" | "redis">;
|
type: Exclude<ServiceType, "application" | "redis">;
|
||||||
}
|
}
|
||||||
export const ShowBackups = ({ id, type }: Props) => {
|
export const ShowBackups = ({ id, type }: Props) => {
|
||||||
const [activeManualBackup, setActiveManualBackup] = useState<string | undefined>();
|
const [activeManualBackup, setActiveManualBackup] = useState<
|
||||||
|
string | undefined
|
||||||
|
>();
|
||||||
const queryMap = {
|
const queryMap = {
|
||||||
postgres: () =>
|
postgres: () =>
|
||||||
api.postgres.one.useQuery({ postgresId: id }, { enabled: !!id }),
|
api.postgres.one.useQuery({ postgresId: id }, { enabled: !!id }),
|
||||||
@@ -142,7 +144,7 @@ export const ShowBackups = ({ id, type }: Props) => {
|
|||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1">
|
||||||
<span className="font-medium">Keep Latest</span>
|
<span className="font-medium">Keep Latest</span>
|
||||||
<span className="text-sm text-muted-foreground">
|
<span className="text-sm text-muted-foreground">
|
||||||
{backup.keepLatestCount || 'All'}
|
{backup.keepLatestCount || "All"}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -153,7 +155,10 @@ export const ShowBackups = ({ id, type }: Props) => {
|
|||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
isLoading={isManualBackup && activeManualBackup === backup.backupId}
|
isLoading={
|
||||||
|
isManualBackup &&
|
||||||
|
activeManualBackup === backup.backupId
|
||||||
|
}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
setActiveManualBackup(backup.backupId);
|
setActiveManualBackup(backup.backupId);
|
||||||
await manualBackup({
|
await manualBackup({
|
||||||
|
|||||||
@@ -92,7 +92,9 @@ export const UpdateBackup = ({ backupId, refetch }: Props) => {
|
|||||||
enabled: backup.enabled || false,
|
enabled: backup.enabled || false,
|
||||||
prefix: backup.prefix,
|
prefix: backup.prefix,
|
||||||
schedule: backup.schedule,
|
schedule: backup.schedule,
|
||||||
keepLatestCount: backup.keepLatestCount ? Number(backup.keepLatestCount) : undefined,
|
keepLatestCount: backup.keepLatestCount
|
||||||
|
? Number(backup.keepLatestCount)
|
||||||
|
: undefined,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [form, form.reset, backup]);
|
}, [form, form.reset, backup]);
|
||||||
@@ -274,10 +276,15 @@ export const UpdateBackup = ({ backupId, refetch }: Props) => {
|
|||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Keep the latest</FormLabel>
|
<FormLabel>Keep the latest</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input type="number" placeholder={"keeps all the backups if left empty"} {...field} />
|
<Input
|
||||||
|
type="number"
|
||||||
|
placeholder={"keeps all the backups if left empty"}
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormDescription>
|
<FormDescription>
|
||||||
Optional. If provided, only keeps the latest N backups in the cloud.
|
Optional. If provided, only keeps the latest N backups
|
||||||
|
in the cloud.
|
||||||
</FormDescription>
|
</FormDescription>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import { AlertBlock } from "@/components/shared/alert-block";
|
||||||
import { ToggleVisibilityInput } from "@/components/shared/toggle-visibility-input";
|
import { ToggleVisibilityInput } from "@/components/shared/toggle-visibility-input";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { AlertBlock } from "@/components/shared/alert-block";
|
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
CardContent,
|
CardContent,
|
||||||
@@ -20,11 +20,11 @@ import { Input } from "@/components/ui/input";
|
|||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import Link from "next/link";
|
||||||
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";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import Link from "next/link";
|
|
||||||
|
|
||||||
const DockerProviderSchema = z.object({
|
const DockerProviderSchema = z.object({
|
||||||
externalPort: z.preprocess((a) => {
|
externalPort: z.preprocess((a) => {
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import {
|
|||||||
TooltipProvider,
|
TooltipProvider,
|
||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from "@/components/ui/tooltip";
|
} from "@/components/ui/tooltip";
|
||||||
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
|
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
||||||
import {
|
import {
|
||||||
Ban,
|
Ban,
|
||||||
CheckCircle2,
|
CheckCircle2,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import { AlertBlock } from "@/components/shared/alert-block";
|
||||||
import { ToggleVisibilityInput } from "@/components/shared/toggle-visibility-input";
|
import { ToggleVisibilityInput } from "@/components/shared/toggle-visibility-input";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { AlertBlock } from "@/components/shared/alert-block";
|
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
CardContent,
|
CardContent,
|
||||||
@@ -20,11 +20,11 @@ import { Input } from "@/components/ui/input";
|
|||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import Link from "next/link";
|
||||||
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";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import Link from "next/link";
|
|
||||||
|
|
||||||
const DockerProviderSchema = z.object({
|
const DockerProviderSchema = z.object({
|
||||||
externalPort: z.preprocess((a) => {
|
externalPort: z.preprocess((a) => {
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import {
|
|||||||
TooltipProvider,
|
TooltipProvider,
|
||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from "@/components/ui/tooltip";
|
} from "@/components/ui/tooltip";
|
||||||
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
|
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
||||||
import {
|
import {
|
||||||
Ban,
|
Ban,
|
||||||
CheckCircle2,
|
CheckCircle2,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import { AlertBlock } from "@/components/shared/alert-block";
|
||||||
import { ToggleVisibilityInput } from "@/components/shared/toggle-visibility-input";
|
import { ToggleVisibilityInput } from "@/components/shared/toggle-visibility-input";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { AlertBlock } from "@/components/shared/alert-block";
|
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
CardContent,
|
CardContent,
|
||||||
@@ -20,11 +20,11 @@ import { Input } from "@/components/ui/input";
|
|||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import Link from "next/link";
|
||||||
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";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import Link from "next/link";
|
|
||||||
|
|
||||||
const DockerProviderSchema = z.object({
|
const DockerProviderSchema = z.object({
|
||||||
externalPort: z.preprocess((a) => {
|
externalPort: z.preprocess((a) => {
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import {
|
|||||||
TooltipProvider,
|
TooltipProvider,
|
||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from "@/components/ui/tooltip";
|
} from "@/components/ui/tooltip";
|
||||||
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
|
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
||||||
import {
|
import {
|
||||||
Ban,
|
Ban,
|
||||||
CheckCircle2,
|
CheckCircle2,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import { AlertBlock } from "@/components/shared/alert-block";
|
||||||
import { ToggleVisibilityInput } from "@/components/shared/toggle-visibility-input";
|
import { ToggleVisibilityInput } from "@/components/shared/toggle-visibility-input";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { AlertBlock } from "@/components/shared/alert-block";
|
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
CardContent,
|
CardContent,
|
||||||
@@ -20,11 +20,11 @@ import { Input } from "@/components/ui/input";
|
|||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import Link from "next/link";
|
||||||
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";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import Link from "next/link";
|
|
||||||
|
|
||||||
const DockerProviderSchema = z.object({
|
const DockerProviderSchema = z.object({
|
||||||
externalPort: z.preprocess((a) => {
|
externalPort: z.preprocess((a) => {
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import {
|
|||||||
TooltipProvider,
|
TooltipProvider,
|
||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from "@/components/ui/tooltip";
|
} from "@/components/ui/tooltip";
|
||||||
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
|
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
||||||
import {
|
import {
|
||||||
Ban,
|
Ban,
|
||||||
CheckCircle2,
|
CheckCircle2,
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ import {
|
|||||||
SearchIcon,
|
SearchIcon,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useState, useEffect } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
|
|
||||||
const TEMPLATE_BASE_URL_KEY = "dokploy_template_base_url";
|
const TEMPLATE_BASE_URL_KEY = "dokploy_template_base_url";
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import {
|
|||||||
} from "@/components/ui/select";
|
} from "@/components/ui/select";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { useState } from "react";
|
|
||||||
|
|
||||||
const examples = [
|
const examples = [
|
||||||
"Make a personal blog",
|
"Make a personal blog",
|
||||||
|
|||||||
@@ -186,7 +186,9 @@ export const ShowProjects = () => {
|
|||||||
target="_blank"
|
target="_blank"
|
||||||
href={`${domain.https ? "https" : "http"}://${domain.host}${domain.path}`}
|
href={`${domain.https ? "https" : "http"}://${domain.host}${domain.path}`}
|
||||||
>
|
>
|
||||||
<span className="truncate">{domain.host}</span>
|
<span className="truncate">
|
||||||
|
{domain.host}
|
||||||
|
</span>
|
||||||
<ExternalLinkIcon className="size-4 shrink-0" />
|
<ExternalLinkIcon className="size-4 shrink-0" />
|
||||||
</Link>
|
</Link>
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
@@ -222,7 +224,9 @@ export const ShowProjects = () => {
|
|||||||
target="_blank"
|
target="_blank"
|
||||||
href={`${domain.https ? "https" : "http"}://${domain.host}${domain.path}`}
|
href={`${domain.https ? "https" : "http"}://${domain.host}${domain.path}`}
|
||||||
>
|
>
|
||||||
<span className="truncate">{domain.host}</span>
|
<span className="truncate">
|
||||||
|
{domain.host}
|
||||||
|
</span>
|
||||||
<ExternalLinkIcon className="size-4 shrink-0" />
|
<ExternalLinkIcon className="size-4 shrink-0" />
|
||||||
</Link>
|
</Link>
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import { AlertBlock } from "@/components/shared/alert-block";
|
||||||
import { ToggleVisibilityInput } from "@/components/shared/toggle-visibility-input";
|
import { ToggleVisibilityInput } from "@/components/shared/toggle-visibility-input";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { AlertBlock } from "@/components/shared/alert-block";
|
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
CardContent,
|
CardContent,
|
||||||
@@ -20,11 +20,11 @@ import { Input } from "@/components/ui/input";
|
|||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import Link from "next/link";
|
||||||
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";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import Link from "next/link";
|
|
||||||
|
|
||||||
const DockerProviderSchema = z.object({
|
const DockerProviderSchema = z.object({
|
||||||
externalPort: z.preprocess((a) => {
|
externalPort: z.preprocess((a) => {
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import {
|
|||||||
TooltipProvider,
|
TooltipProvider,
|
||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from "@/components/ui/tooltip";
|
} from "@/components/ui/tooltip";
|
||||||
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
|
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
||||||
import {
|
import {
|
||||||
Ban,
|
Ban,
|
||||||
CheckCircle2,
|
CheckCircle2,
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { api } from "@/utils/api";
|
|
||||||
import {
|
import {
|
||||||
type ChartConfig,
|
type ChartConfig,
|
||||||
ChartContainer,
|
ChartContainer,
|
||||||
ChartTooltip,
|
ChartTooltip,
|
||||||
ChartTooltipContent,
|
ChartTooltipContent,
|
||||||
} from "@/components/ui/chart";
|
} from "@/components/ui/chart";
|
||||||
|
import { api } from "@/utils/api";
|
||||||
import {
|
import {
|
||||||
Area,
|
Area,
|
||||||
AreaChart,
|
AreaChart,
|
||||||
|
|||||||
@@ -25,13 +25,13 @@ import {
|
|||||||
import { type RouterOutputs, api } from "@/utils/api";
|
import { type RouterOutputs, api } from "@/utils/api";
|
||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
import {
|
import {
|
||||||
ArrowDownUp,
|
|
||||||
AlertCircle,
|
AlertCircle,
|
||||||
InfoIcon,
|
ArrowDownUp,
|
||||||
Calendar as CalendarIcon,
|
Calendar as CalendarIcon,
|
||||||
|
InfoIcon,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useState, useEffect } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { RequestDistributionChart } from "./request-distribution-chart";
|
import { RequestDistributionChart } from "./request-distribution-chart";
|
||||||
import { RequestsTable } from "./requests-table";
|
import { RequestsTable } from "./requests-table";
|
||||||
|
|||||||
@@ -1,14 +1,22 @@
|
|||||||
|
import { CodeEditor } from "@/components/shared/code-editor";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { api } from "@/utils/api";
|
|
||||||
import { toast } from "sonner";
|
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
DialogHeader,
|
DialogHeader,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
DialogTrigger,
|
DialogTrigger,
|
||||||
DialogDescription,
|
|
||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/dialog";
|
||||||
|
import {
|
||||||
|
Form,
|
||||||
|
FormControl,
|
||||||
|
FormDescription,
|
||||||
|
FormField,
|
||||||
|
FormItem,
|
||||||
|
FormLabel,
|
||||||
|
FormMessage,
|
||||||
|
} from "@/components/ui/form";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import {
|
import {
|
||||||
Select,
|
Select,
|
||||||
@@ -17,22 +25,14 @@ import {
|
|||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "@/components/ui/select";
|
} from "@/components/ui/select";
|
||||||
|
import { Switch } from "@/components/ui/switch";
|
||||||
|
import { api } from "@/utils/api";
|
||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import copy from "copy-to-clipboard";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { toast } from "sonner";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import {
|
|
||||||
Form,
|
|
||||||
FormControl,
|
|
||||||
FormField,
|
|
||||||
FormItem,
|
|
||||||
FormLabel,
|
|
||||||
FormMessage,
|
|
||||||
FormDescription,
|
|
||||||
} from "@/components/ui/form";
|
|
||||||
import { Switch } from "@/components/ui/switch";
|
|
||||||
import copy from "copy-to-clipboard";
|
|
||||||
import { CodeEditor } from "@/components/shared/code-editor";
|
|
||||||
|
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
name: z.string().min(1, "Name is required"),
|
name: z.string().min(1, "Name is required"),
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { DialogAction } from "@/components/shared/dialog-action";
|
||||||
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
@@ -7,13 +9,11 @@ import {
|
|||||||
CardTitle,
|
CardTitle,
|
||||||
} from "@/components/ui/card";
|
} from "@/components/ui/card";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { ExternalLinkIcon, KeyIcon, Trash2, Clock, Tag } from "lucide-react";
|
import { formatDistanceToNow } from "date-fns";
|
||||||
|
import { Clock, ExternalLinkIcon, KeyIcon, Tag, Trash2 } from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { formatDistanceToNow } from "date-fns";
|
|
||||||
import { DialogAction } from "@/components/shared/dialog-action";
|
|
||||||
import { AddApiKey } from "./add-api-key";
|
import { AddApiKey } from "./add-api-key";
|
||||||
import { Badge } from "@/components/ui/badge";
|
|
||||||
|
|
||||||
export const ShowApiKeys = () => {
|
export const ShowApiKeys = () => {
|
||||||
const { data, refetch } = api.user.get.useQuery();
|
const { data, refetch } = api.user.get.useQuery();
|
||||||
|
|||||||
@@ -35,9 +35,9 @@ import { api } from "@/utils/api";
|
|||||||
import {
|
import {
|
||||||
Boxes,
|
Boxes,
|
||||||
HelpCircle,
|
HelpCircle,
|
||||||
|
Loader2,
|
||||||
LockIcon,
|
LockIcon,
|
||||||
MoreHorizontal,
|
MoreHorizontal,
|
||||||
Loader2,
|
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { AddNode } from "./add-node";
|
import { AddNode } from "./add-node";
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ export const AddGiteaProvider = () => {
|
|||||||
const utils = api.useUtils();
|
const utils = api.useUtils();
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const url = useUrl();
|
const url = useUrl();
|
||||||
const { data: auth } = api.user.get.useQuery();
|
|
||||||
const { mutateAsync, error, isError } = api.gitea.create.useMutation(); // Updated API call for Gitea
|
const { mutateAsync, error, isError } = api.gitea.create.useMutation(); // Updated API call for Gitea
|
||||||
const webhookUrl = `${url}/api/providers/gitea/callback`; // Updated webhook URL for Gitea
|
const webhookUrl = `${url}/api/providers/gitea/callback`; // Updated webhook URL for Gitea
|
||||||
|
|
||||||
@@ -149,12 +148,15 @@ 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>
|
<li>
|
||||||
|
Select Permissions - organization: read, user: read,
|
||||||
|
repository: read/write
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
After creating, you'll receive an ID and Secret,
|
After creating, you'll receive an ID and Secret, copy them
|
||||||
copy them and paste them below.
|
and paste them below.
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
<FormField
|
<FormField
|
||||||
|
|||||||
@@ -20,11 +20,11 @@ import { api } from "@/utils/api";
|
|||||||
import { useUrl } from "@/utils/hooks/use-url";
|
import { useUrl } from "@/utils/hooks/use-url";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { PenBoxIcon } from "lucide-react";
|
import { PenBoxIcon } from "lucide-react";
|
||||||
import { useState, useEffect } from "react";
|
import { useRouter } from "next/router";
|
||||||
|
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";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { useRouter } from 'next/router';
|
|
||||||
|
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
name: z.string().min(1, "Name is required"),
|
name: z.string().min(1, "Name is required"),
|
||||||
@@ -40,9 +40,14 @@ interface Props {
|
|||||||
export const EditGiteaProvider = ({ giteaId }: Props) => {
|
export const EditGiteaProvider = ({ giteaId }: Props) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const { data: gitea, isLoading, refetch } = api.gitea.one.useQuery({ giteaId });
|
const {
|
||||||
|
data: gitea,
|
||||||
|
isLoading,
|
||||||
|
refetch,
|
||||||
|
} = api.gitea.one.useQuery({ giteaId });
|
||||||
const { mutateAsync, isLoading: isUpdating } = api.gitea.update.useMutation();
|
const { mutateAsync, isLoading: isUpdating } = api.gitea.update.useMutation();
|
||||||
const { mutateAsync: testConnection, isLoading: isTesting } = api.gitea.testConnection.useMutation();
|
const { mutateAsync: testConnection, isLoading: isTesting } =
|
||||||
|
api.gitea.testConnection.useMutation();
|
||||||
const url = useUrl();
|
const url = useUrl();
|
||||||
const utils = api.useUtils();
|
const utils = api.useUtils();
|
||||||
|
|
||||||
@@ -56,26 +61,34 @@ export const EditGiteaProvider = ({ giteaId }: Props) => {
|
|||||||
if (connected) {
|
if (connected) {
|
||||||
toast.success("Successfully connected to Gitea", {
|
toast.success("Successfully connected to Gitea", {
|
||||||
description: "Your Gitea provider has been authorized.",
|
description: "Your Gitea provider has been authorized.",
|
||||||
id: 'gitea-connection-success'
|
id: "gitea-connection-success",
|
||||||
});
|
});
|
||||||
refetch();
|
refetch();
|
||||||
// Clear the query parameters to prevent re-triggering
|
// Clear the query parameters to prevent re-triggering
|
||||||
router.replace({
|
router.replace(
|
||||||
|
{
|
||||||
pathname: router.pathname,
|
pathname: router.pathname,
|
||||||
query: {}
|
query: {},
|
||||||
}, undefined, { shallow: true });
|
},
|
||||||
|
undefined,
|
||||||
|
{ shallow: true },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
toast.error("Gitea Connection Failed", {
|
toast.error("Gitea Connection Failed", {
|
||||||
description: decodeURIComponent(error as string),
|
description: decodeURIComponent(error as string),
|
||||||
id: 'gitea-connection-error'
|
id: "gitea-connection-error",
|
||||||
});
|
});
|
||||||
// Clear the query parameters to prevent re-triggering
|
// Clear the query parameters to prevent re-triggering
|
||||||
router.replace({
|
router.replace(
|
||||||
|
{
|
||||||
pathname: router.pathname,
|
pathname: router.pathname,
|
||||||
query: {}
|
query: {},
|
||||||
}, undefined, { shallow: true });
|
},
|
||||||
|
undefined,
|
||||||
|
{ shallow: true },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}, [router.query, router.isReady, refetch]);
|
}, [router.query, router.isReady, refetch]);
|
||||||
|
|
||||||
@@ -125,17 +138,21 @@ export const EditGiteaProvider = ({ giteaId }: Props) => {
|
|||||||
try {
|
try {
|
||||||
const result = await testConnection({ giteaId });
|
const result = await testConnection({ giteaId });
|
||||||
toast.success("Gitea Connection Verified", {
|
toast.success("Gitea Connection Verified", {
|
||||||
description: result
|
description: result,
|
||||||
});
|
});
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
const authUrl = error.authorizationUrl || getGiteaOAuthUrl();
|
const authUrl = error.authorizationUrl || getGiteaOAuthUrl();
|
||||||
|
|
||||||
toast.error("Gitea Not Connected", {
|
toast.error("Gitea Not Connected", {
|
||||||
description: error.message || "Please complete the OAuth authorization process.",
|
description:
|
||||||
action: authUrl && authUrl !== "#" ? {
|
error.message || "Please complete the OAuth authorization process.",
|
||||||
|
action:
|
||||||
|
authUrl && authUrl !== "#"
|
||||||
|
? {
|
||||||
label: "Authorize Now",
|
label: "Authorize Now",
|
||||||
onClick: () => window.open(authUrl, "_blank")
|
onClick: () => window.open(authUrl, "_blank"),
|
||||||
} : undefined,
|
}
|
||||||
|
: undefined,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -147,7 +164,7 @@ export const EditGiteaProvider = ({ giteaId }: Props) => {
|
|||||||
|
|
||||||
if (!clientId || !giteaUrl) {
|
if (!clientId || !giteaUrl) {
|
||||||
toast.error("Configuration Incomplete", {
|
toast.error("Configuration Incomplete", {
|
||||||
description: "Please fill in Client ID and Gitea URL first."
|
description: "Please fill in Client ID and Gitea URL first.",
|
||||||
});
|
});
|
||||||
return "#";
|
return "#";
|
||||||
}
|
}
|
||||||
@@ -155,7 +172,9 @@ export const EditGiteaProvider = ({ giteaId }: Props) => {
|
|||||||
const redirectUri = `${url}/api/providers/gitea/callback`;
|
const redirectUri = `${url}/api/providers/gitea/callback`;
|
||||||
|
|
||||||
// Use the scopes from the gitea data (if available), else fallback to default scopes
|
// Use the scopes from the gitea data (if available), else fallback to default scopes
|
||||||
const scopes = gitea?.scopes?.split(',').join(' ') || 'repo repo:status read:user read:org';
|
const scopes =
|
||||||
|
gitea?.scopes?.split(",").join(" ") ||
|
||||||
|
"repo repo:status read:user read:org";
|
||||||
//const scopes = gitea?.scopes || 'repo,repo:status,read:user,read:org';
|
//const scopes = gitea?.scopes || 'repo,repo:status,read:user,read:org';
|
||||||
|
|
||||||
const state = giteaId;
|
const state = giteaId;
|
||||||
@@ -175,7 +194,11 @@ export const EditGiteaProvider = ({ giteaId }: Props) => {
|
|||||||
return (
|
return (
|
||||||
<Dialog open={open} onOpenChange={setOpen}>
|
<Dialog open={open} onOpenChange={setOpen}>
|
||||||
<DialogTrigger asChild>
|
<DialogTrigger asChild>
|
||||||
<Button variant="ghost" size="icon" className="group hover:bg-blue-500/10">
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
className="group hover:bg-blue-500/10"
|
||||||
|
>
|
||||||
<PenBoxIcon className="size-3.5 text-primary group-hover:text-blue-500" />
|
<PenBoxIcon className="size-3.5 text-primary group-hover:text-blue-500" />
|
||||||
</Button>
|
</Button>
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
|
|||||||
@@ -1,36 +1,43 @@
|
|||||||
import {
|
import {
|
||||||
BitbucketIcon,
|
BitbucketIcon,
|
||||||
|
GiteaIcon,
|
||||||
GithubIcon,
|
GithubIcon,
|
||||||
GitlabIcon,
|
GitlabIcon,
|
||||||
GiteaIcon,
|
} from "@/components/icons/data-tools-icons";
|
||||||
} from "@/components/icons/data-tools-icons";
|
import { DialogAction } from "@/components/shared/dialog-action";
|
||||||
import { DialogAction } from "@/components/shared/dialog-action";
|
import { Button, buttonVariants } from "@/components/ui/button";
|
||||||
import { Button, buttonVariants } from "@/components/ui/button";
|
import {
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
Card,
|
||||||
import { api } from "@/utils/api";
|
CardContent,
|
||||||
import { useUrl } from "@/utils/hooks/use-url";
|
CardDescription,
|
||||||
import { formatDate } from "date-fns";
|
CardHeader,
|
||||||
import {
|
CardTitle,
|
||||||
|
} from "@/components/ui/card";
|
||||||
|
import { api } from "@/utils/api";
|
||||||
|
import { useUrl } from "@/utils/hooks/use-url";
|
||||||
|
import { formatDate } from "date-fns";
|
||||||
|
import {
|
||||||
ExternalLinkIcon,
|
ExternalLinkIcon,
|
||||||
GitBranch,
|
GitBranch,
|
||||||
ImportIcon,
|
ImportIcon,
|
||||||
Loader2,
|
Loader2,
|
||||||
Trash2,
|
Trash2,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { AddBitbucketProvider } from "./bitbucket/add-bitbucket-provider";
|
import { AddBitbucketProvider } from "./bitbucket/add-bitbucket-provider";
|
||||||
import { EditBitbucketProvider } from "./bitbucket/edit-bitbucket-provider";
|
import { EditBitbucketProvider } from "./bitbucket/edit-bitbucket-provider";
|
||||||
import { AddGithubProvider } from "./github/add-github-provider";
|
import { AddGiteaProvider } from "./gitea/add-gitea-provider";
|
||||||
import { EditGithubProvider } from "./github/edit-github-provider";
|
import { EditGiteaProvider } from "./gitea/edit-gitea-provider";
|
||||||
import { AddGitlabProvider } from "./gitlab/add-gitlab-provider";
|
import { AddGithubProvider } from "./github/add-github-provider";
|
||||||
import { EditGitlabProvider } from "./gitlab/edit-gitlab-provider";
|
import { EditGithubProvider } from "./github/edit-github-provider";
|
||||||
import { AddGiteaProvider } from "./gitea/add-gitea-provider";
|
import { AddGitlabProvider } from "./gitlab/add-gitlab-provider";
|
||||||
import { EditGiteaProvider } from "./gitea/edit-gitea-provider";
|
import { EditGitlabProvider } from "./gitlab/edit-gitlab-provider";
|
||||||
|
|
||||||
export const ShowGitProviders = () => {
|
export const ShowGitProviders = () => {
|
||||||
const { data, isLoading, refetch } = api.gitProvider.getAll.useQuery();
|
const { data, isLoading, refetch } = api.gitProvider.getAll.useQuery();
|
||||||
const { mutateAsync, isLoading: isRemoving } = api.gitProvider.remove.useMutation();
|
const { mutateAsync, isLoading: isRemoving } =
|
||||||
|
api.gitProvider.remove.useMutation();
|
||||||
const url = useUrl();
|
const url = useUrl();
|
||||||
|
|
||||||
const getGitlabUrl = (
|
const getGitlabUrl = (
|
||||||
@@ -44,17 +51,6 @@ import {
|
|||||||
return authUrl;
|
return authUrl;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getGiteaUrl = (
|
|
||||||
clientId: string,
|
|
||||||
giteaId: string,
|
|
||||||
giteaUrl: string,
|
|
||||||
) => {
|
|
||||||
const redirectUri = `${url}/api/providers/gitea/callback?giteaId=${giteaId}`;
|
|
||||||
const scope = "repo";
|
|
||||||
const authUrl = `${giteaUrl}/login/oauth/authorize?client_id=${clientId}&redirect_uri=${encodeURIComponent(redirectUri)}&response_type=code&scope=${encodeURIComponent(scope)}`;
|
|
||||||
return authUrl;
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<Card className="h-full bg-sidebar p-2.5 rounded-xl max-w-5xl mx-auto">
|
<Card className="h-full bg-sidebar p-2.5 rounded-xl max-w-5xl mx-auto">
|
||||||
@@ -113,19 +109,23 @@ import {
|
|||||||
{data?.map((gitProvider, _index) => {
|
{data?.map((gitProvider, _index) => {
|
||||||
const isGithub = gitProvider.providerType === "github";
|
const isGithub = gitProvider.providerType === "github";
|
||||||
const isGitlab = gitProvider.providerType === "gitlab";
|
const isGitlab = gitProvider.providerType === "gitlab";
|
||||||
const isBitbucket = gitProvider.providerType === "bitbucket";
|
const isBitbucket =
|
||||||
|
gitProvider.providerType === "bitbucket";
|
||||||
const isGitea = gitProvider.providerType === "gitea";
|
const isGitea = gitProvider.providerType === "gitea";
|
||||||
|
|
||||||
const haveGithubRequirements = isGithub &&
|
const haveGithubRequirements =
|
||||||
|
isGithub &&
|
||||||
gitProvider.github?.githubPrivateKey &&
|
gitProvider.github?.githubPrivateKey &&
|
||||||
gitProvider.github?.githubAppId &&
|
gitProvider.github?.githubAppId &&
|
||||||
gitProvider.github?.githubInstallationId;
|
gitProvider.github?.githubInstallationId;
|
||||||
|
|
||||||
const haveGitlabRequirements = isGitlab &&
|
const haveGitlabRequirements =
|
||||||
|
isGitlab &&
|
||||||
gitProvider.gitlab?.accessToken &&
|
gitProvider.gitlab?.accessToken &&
|
||||||
gitProvider.gitlab?.refreshToken;
|
gitProvider.gitlab?.refreshToken;
|
||||||
|
|
||||||
const haveGiteaRequirements = isGitea &&
|
const haveGiteaRequirements =
|
||||||
|
isGitea &&
|
||||||
gitProvider.gitea?.accessToken &&
|
gitProvider.gitea?.accessToken &&
|
||||||
gitProvider.gitea?.refreshToken;
|
gitProvider.gitea?.refreshToken;
|
||||||
|
|
||||||
@@ -146,9 +146,7 @@ import {
|
|||||||
{isBitbucket && (
|
{isBitbucket && (
|
||||||
<BitbucketIcon className="size-5" />
|
<BitbucketIcon className="size-5" />
|
||||||
)}
|
)}
|
||||||
{isGitea && (
|
{isGitea && <GiteaIcon className="size-5" />}
|
||||||
<GiteaIcon className="size-5" />
|
|
||||||
)}
|
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1">
|
||||||
<span className="text-sm font-medium">
|
<span className="text-sm font-medium">
|
||||||
{gitProvider.name}
|
{gitProvider.name}
|
||||||
@@ -156,7 +154,7 @@ import {
|
|||||||
<span className="text-xs text-muted-foreground">
|
<span className="text-xs text-muted-foreground">
|
||||||
{formatDate(
|
{formatDate(
|
||||||
gitProvider.createdAt,
|
gitProvider.createdAt,
|
||||||
"yyyy-MM-dd hh:mm:ss a"
|
"yyyy-MM-dd hh:mm:ss a",
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -210,19 +208,29 @@ import {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{isGithub && haveGithubRequirements && (
|
{isGithub && haveGithubRequirements && (
|
||||||
<EditGithubProvider githubId={gitProvider.github?.githubId} />
|
<EditGithubProvider
|
||||||
|
githubId={gitProvider.github?.githubId}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isGitlab && (
|
{isGitlab && (
|
||||||
<EditGitlabProvider gitlabId={gitProvider.gitlab?.gitlabId} />
|
<EditGitlabProvider
|
||||||
|
gitlabId={gitProvider.gitlab?.gitlabId}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isBitbucket && (
|
{isBitbucket && (
|
||||||
<EditBitbucketProvider bitbucketId={gitProvider.bitbucket?.bitbucketId} />
|
<EditBitbucketProvider
|
||||||
|
bitbucketId={
|
||||||
|
gitProvider.bitbucket?.bitbucketId
|
||||||
|
}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isGitea && (
|
{isGitea && (
|
||||||
<EditGiteaProvider giteaId={gitProvider.gitea?.giteaId} />
|
<EditGiteaProvider
|
||||||
|
giteaId={gitProvider.gitea?.giteaId}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<DialogAction
|
<DialogAction
|
||||||
@@ -234,11 +242,15 @@ import {
|
|||||||
gitProviderId: gitProvider.gitProviderId,
|
gitProviderId: gitProvider.gitProviderId,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
toast.success("Git Provider deleted successfully");
|
toast.success(
|
||||||
|
"Git Provider deleted successfully",
|
||||||
|
);
|
||||||
refetch();
|
refetch();
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
toast.error("Error deleting Git Provider");
|
toast.error(
|
||||||
|
"Error deleting Git Provider",
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -270,4 +282,4 @@ import {
|
|||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import { useTranslation } from "next-i18next";
|
|||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
|
import { ShowNodesModal } from "../cluster/nodes/show-nodes-modal";
|
||||||
import { TerminalModal } from "../web-server/terminal-modal";
|
import { TerminalModal } from "../web-server/terminal-modal";
|
||||||
import { ShowServerActions } from "./actions/show-server-actions";
|
import { ShowServerActions } from "./actions/show-server-actions";
|
||||||
import { HandleServers } from "./handle-servers";
|
import { HandleServers } from "./handle-servers";
|
||||||
@@ -42,7 +43,6 @@ import { ShowMonitoringModal } from "./show-monitoring-modal";
|
|||||||
import { ShowSwarmOverviewModal } from "./show-swarm-overview-modal";
|
import { ShowSwarmOverviewModal } from "./show-swarm-overview-modal";
|
||||||
import { ShowTraefikFileSystemModal } from "./show-traefik-file-system-modal";
|
import { ShowTraefikFileSystemModal } from "./show-traefik-file-system-modal";
|
||||||
import { WelcomeSuscription } from "./welcome-stripe/welcome-suscription";
|
import { WelcomeSuscription } from "./welcome-stripe/welcome-suscription";
|
||||||
import { ShowNodesModal } from "../cluster/nodes/show-nodes-modal";
|
|
||||||
|
|
||||||
export const ShowServers = () => {
|
export const ShowServers = () => {
|
||||||
const { t } = useTranslation("settings");
|
const { t } = useTranslation("settings");
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { Badge } from "@/components/ui/badge";
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
@@ -22,7 +23,6 @@ import dynamic from "next/dynamic";
|
|||||||
import type React from "react";
|
import type React from "react";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { badgeStateColor } from "../../application/logs/show";
|
import { badgeStateColor } from "../../application/logs/show";
|
||||||
import { Badge } from "@/components/ui/badge";
|
|
||||||
|
|
||||||
export const DockerLogsId = dynamic(
|
export const DockerLogsId = dynamic(
|
||||||
() =>
|
() =>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import {
|
|||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { DatabaseIcon, AlertTriangle } from "lucide-react";
|
import { AlertTriangle, DatabaseIcon } from "lucide-react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { ShowCustomCommand } from "@/components/dashboard/postgres/advanced/show-custom-command";
|
|
||||||
import { ShowResources } from "@/components/dashboard/application/advanced/show-resources";
|
import { ShowResources } from "@/components/dashboard/application/advanced/show-resources";
|
||||||
import { ShowVolumes } from "@/components/dashboard/application/advanced/volumes/show-volumes";
|
import { ShowVolumes } from "@/components/dashboard/application/advanced/volumes/show-volumes";
|
||||||
|
import { ShowCustomCommand } from "@/components/dashboard/postgres/advanced/show-custom-command";
|
||||||
import { RebuildDatabase } from "./rebuild-database";
|
import { RebuildDatabase } from "./rebuild-database";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|||||||
@@ -253,17 +253,17 @@ export const GiteaIcon = ({ className }: Props) => {
|
|||||||
<g>
|
<g>
|
||||||
<path
|
<path
|
||||||
id="teabag"
|
id="teabag"
|
||||||
style={{ fill: '#FFFFFF' }}
|
style={{ fill: "#FFFFFF" }}
|
||||||
d="M395.9,484.2l-126.9-61c-12.5-6-17.9-21.2-11.8-33.8l61-126.9c6-12.5,21.2-17.9,33.8-11.8c17.2,8.3,27.1,13,27.1,13l-0.1-109.2l16.7-0.1l0.1,117.1c0,0,57.4,24.2,83.1,40.1c3.7,2.3,10.2,6.8,12.9,14.4c2.1,6.1,2,13.1-1,19.3l-61,126.9C423.6,484.9,408.4,490.3,395.9,484.2z"
|
d="M395.9,484.2l-126.9-61c-12.5-6-17.9-21.2-11.8-33.8l61-126.9c6-12.5,21.2-17.9,33.8-11.8c17.2,8.3,27.1,13,27.1,13l-0.1-109.2l16.7-0.1l0.1,117.1c0,0,57.4,24.2,83.1,40.1c3.7,2.3,10.2,6.8,12.9,14.4c2.1,6.1,2,13.1-1,19.3l-61,126.9C423.6,484.9,408.4,490.3,395.9,484.2z"
|
||||||
/>
|
/>
|
||||||
<g>
|
<g>
|
||||||
<g>
|
<g>
|
||||||
<path
|
<path
|
||||||
style={{ fill: '#609926' }}
|
style={{ fill: "#609926" }}
|
||||||
d="M622.7,149.8c-4.1-4.1-9.6-4-9.6-4s-117.2,6.6-177.9,8c-13.3,0.3-26.5,0.6-39.6,0.7c0,39.1,0,78.2,0,117.2c-5.5-2.6-11.1-5.3-16.6-7.9c0-36.4-0.1-109.2-0.1-109.2c-29,0.4-89.2-2.2-89.2-2.2s-141.4-7.1-156.8-8.5c-9.8-0.6-22.5-2.1-39,1.5c-8.7,1.8-33.5,7.4-53.8,26.9C-4.9,212.4,6.6,276.2,8,285.8c1.7,11.7,6.9,44.2,31.7,72.5c45.8,56.1,144.4,54.8,144.4,54.8s12.1,28.9,30.6,55.5c25,33.1,50.7,58.9,75.7,62c63,0,188.9-0.1,188.9-0.1s12,0.1,28.3-10.3c14-8.5,26.5-23.4,26.5-23.4s12.9-13.8,30.9-45.3c5.5-9.7,10.1-19.1,14.1-28c0,0,55.2-117.1,55.2-231.1C633.2,157.9,624.7,151.8,622.7,149.8z M125.6,353.9c-25.9-8.5-36.9-18.7-36.9-18.7S69.6,321.8,60,295.4c-16.5-44.2-1.4-71.2-1.4-71.2s8.4-22.5,38.5-30c13.8-3.7,31-3.1,31-3.1s7.1,59.4,15.7,94.2c7.2,29.2,24.8,77.7,24.8,77.7S142.5,359.9,125.6,353.9z M425.9,461.5c0,0-6.1,14.5-19.6,15.4c-5.8,0.4-10.3-1.2-10.3-1.2s-0.3-0.1-5.3-2.1l-112.9-55c0,0-10.9-5.7-12.8-15.6c-2.2-8.1,2.7-18.1,2.7-18.1L322,273c0,0,4.8-9.7,12.2-13c0.6-0.3,2.3-1,4.5-1.5c8.1-2.1,18,2.8,18,2.8l110.7,53.7c0,0,12.6,5.7,15.3,16.2c1.9,7.4-0.5,14-1.8,17.2C474.6,363.8,425.9,461.5,425.9,461.5z"
|
d="M622.7,149.8c-4.1-4.1-9.6-4-9.6-4s-117.2,6.6-177.9,8c-13.3,0.3-26.5,0.6-39.6,0.7c0,39.1,0,78.2,0,117.2c-5.5-2.6-11.1-5.3-16.6-7.9c0-36.4-0.1-109.2-0.1-109.2c-29,0.4-89.2-2.2-89.2-2.2s-141.4-7.1-156.8-8.5c-9.8-0.6-22.5-2.1-39,1.5c-8.7,1.8-33.5,7.4-53.8,26.9C-4.9,212.4,6.6,276.2,8,285.8c1.7,11.7,6.9,44.2,31.7,72.5c45.8,56.1,144.4,54.8,144.4,54.8s12.1,28.9,30.6,55.5c25,33.1,50.7,58.9,75.7,62c63,0,188.9-0.1,188.9-0.1s12,0.1,28.3-10.3c14-8.5,26.5-23.4,26.5-23.4s12.9-13.8,30.9-45.3c5.5-9.7,10.1-19.1,14.1-28c0,0,55.2-117.1,55.2-231.1C633.2,157.9,624.7,151.8,622.7,149.8z M125.6,353.9c-25.9-8.5-36.9-18.7-36.9-18.7S69.6,321.8,60,295.4c-16.5-44.2-1.4-71.2-1.4-71.2s8.4-22.5,38.5-30c13.8-3.7,31-3.1,31-3.1s7.1,59.4,15.7,94.2c7.2,29.2,24.8,77.7,24.8,77.7S142.5,359.9,125.6,353.9z M425.9,461.5c0,0-6.1,14.5-19.6,15.4c-5.8,0.4-10.3-1.2-10.3-1.2s-0.3-0.1-5.3-2.1l-112.9-55c0,0-10.9-5.7-12.8-15.6c-2.2-8.1,2.7-18.1,2.7-18.1L322,273c0,0,4.8-9.7,12.2-13c0.6-0.3,2.3-1,4.5-1.5c8.1-2.1,18,2.8,18,2.8l110.7,53.7c0,0,12.6,5.7,15.3,16.2c1.9,7.4-0.5,14-1.8,17.2C474.6,363.8,425.9,461.5,425.9,461.5z"
|
||||||
/>
|
/>
|
||||||
<path
|
<path
|
||||||
style={{ fill: '#609926' }}
|
style={{ fill: "#609926" }}
|
||||||
d="M326.8,380.1c-8.2,0.1-15.4,5.8-17.3,13.8c-1.9,8,2,16.3,9.1,20c7.7,4,17.5,1.8,22.7-5.4c5.1-7.1,4.3-16.9-1.8-23.1l24-49.1c1.5,0.1,3.7,0.2,6.2-0.5c4.1-0.9,7.1-3.6,7.1-3.6c4.2,1.8,8.6,3.8,13.2,6.1c4.8,2.4,9.3,4.9,13.4,7.3c0.9,0.5,1.8,1.1,2.8,1.9c1.6,1.3,3.4,3.1,4.7,5.5c1.9,5.5-1.9,14.9-1.9,14.9c-2.3,7.6-18.4,40.6-18.4,40.6c-8.1-0.2-15.3,5-17.7,12.5c-2.6,8.1,1.1,17.3,8.9,21.3c7.8,4,17.4,1.7,22.5-5.3c5-6.8,4.6-16.3-1.1-22.6c1.9-3.7,3.7-7.4,5.6-11.3c5-10.4,13.5-30.4,13.5-30.4c0.9-1.7,5.7-10.3,2.7-21.3c-2.5-11.4-12.6-16.7-12.6-16.7c-12.2-7.9-29.2-15.2-29.2-15.2s0-4.1-1.1-7.1c-1.1-3.1-2.8-5.1-3.9-6.3c4.7-9.7,9.4-19.3,14.1-29c-4.1-2-8.1-4-12.2-6.1c-4.8,9.8-9.7,19.7-14.5,29.5c-6.7-0.1-12.9,3.5-16.1,9.4c-3.4,6.3-2.7,14.1,1.9,19.8C343.2,346.5,335,363.3,326.8,380.1z"
|
d="M326.8,380.1c-8.2,0.1-15.4,5.8-17.3,13.8c-1.9,8,2,16.3,9.1,20c7.7,4,17.5,1.8,22.7-5.4c5.1-7.1,4.3-16.9-1.8-23.1l24-49.1c1.5,0.1,3.7,0.2,6.2-0.5c4.1-0.9,7.1-3.6,7.1-3.6c4.2,1.8,8.6,3.8,13.2,6.1c4.8,2.4,9.3,4.9,13.4,7.3c0.9,0.5,1.8,1.1,2.8,1.9c1.6,1.3,3.4,3.1,4.7,5.5c1.9,5.5-1.9,14.9-1.9,14.9c-2.3,7.6-18.4,40.6-18.4,40.6c-8.1-0.2-15.3,5-17.7,12.5c-2.6,8.1,1.1,17.3,8.9,21.3c7.8,4,17.4,1.7,22.5-5.3c5-6.8,4.6-16.3-1.1-22.6c1.9-3.7,3.7-7.4,5.6-11.3c5-10.4,13.5-30.4,13.5-30.4c0.9-1.7,5.7-10.3,2.7-21.3c-2.5-11.4-12.6-16.7-12.6-16.7c-12.2-7.9-29.2-15.2-29.2-15.2s0-4.1-1.1-7.1c-1.1-3.1-2.8-5.1-3.9-6.3c4.7-9.7,9.4-19.3,14.1-29c-4.1-2-8.1-4-12.2-6.1c-4.8,9.8-9.7,19.7-14.5,29.5c-6.7-0.1-12.9,3.5-16.1,9.4c-3.4,6.3-2.7,14.1,1.9,19.8C343.2,346.5,335,363.3,326.8,380.1z"
|
||||||
/>
|
/>
|
||||||
</g>
|
</g>
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import type { IUpdateData } from "@dokploy/server/index";
|
import type { IUpdateData } from "@dokploy/server/index";
|
||||||
|
import { Download } from "lucide-react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import UpdateServer from "../dashboard/settings/web-server/update-server";
|
import UpdateServer from "../dashboard/settings/web-server/update-server";
|
||||||
import { Button } from "../ui/button";
|
import { Button } from "../ui/button";
|
||||||
import { Download } from "lucide-react";
|
|
||||||
import {
|
import {
|
||||||
Tooltip,
|
Tooltip,
|
||||||
TooltipContent,
|
TooltipContent,
|
||||||
|
|||||||
@@ -37,7 +37,9 @@ export const BreadcrumbSidebar = ({ list }: Props) => {
|
|||||||
)}
|
)}
|
||||||
</BreadcrumbLink>
|
</BreadcrumbLink>
|
||||||
</BreadcrumbItem>
|
</BreadcrumbItem>
|
||||||
{_index + 1 < list.length && <BreadcrumbSeparator className="block" />}
|
{_index + 1 < list.length && (
|
||||||
|
<BreadcrumbSeparator className="block" />
|
||||||
|
)}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</BreadcrumbList>
|
</BreadcrumbList>
|
||||||
|
|||||||
@@ -3,18 +3,18 @@ import { json } from "@codemirror/lang-json";
|
|||||||
import { yaml } from "@codemirror/lang-yaml";
|
import { yaml } from "@codemirror/lang-yaml";
|
||||||
import { StreamLanguage } from "@codemirror/language";
|
import { StreamLanguage } from "@codemirror/language";
|
||||||
|
|
||||||
|
import {
|
||||||
|
type Completion,
|
||||||
|
type CompletionContext,
|
||||||
|
type CompletionResult,
|
||||||
|
autocompletion,
|
||||||
|
} from "@codemirror/autocomplete";
|
||||||
import { properties } from "@codemirror/legacy-modes/mode/properties";
|
import { properties } from "@codemirror/legacy-modes/mode/properties";
|
||||||
import { shell } from "@codemirror/legacy-modes/mode/shell";
|
import { shell } from "@codemirror/legacy-modes/mode/shell";
|
||||||
import { EditorView } from "@codemirror/view";
|
import { EditorView } from "@codemirror/view";
|
||||||
import { githubDark, githubLight } from "@uiw/codemirror-theme-github";
|
import { githubDark, githubLight } from "@uiw/codemirror-theme-github";
|
||||||
import CodeMirror, { type ReactCodeMirrorProps } from "@uiw/react-codemirror";
|
import CodeMirror, { type ReactCodeMirrorProps } from "@uiw/react-codemirror";
|
||||||
import { useTheme } from "next-themes";
|
import { useTheme } from "next-themes";
|
||||||
import {
|
|
||||||
autocompletion,
|
|
||||||
type CompletionContext,
|
|
||||||
type CompletionResult,
|
|
||||||
type Completion,
|
|
||||||
} from "@codemirror/autocomplete";
|
|
||||||
|
|
||||||
// Docker Compose completion options
|
// Docker Compose completion options
|
||||||
const dockerComposeServices = [
|
const dockerComposeServices = [
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import type * as React from "react";
|
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
|
import type * as React from "react";
|
||||||
import { DayPicker } from "react-day-picker";
|
import { DayPicker } from "react-day-picker";
|
||||||
|
|
||||||
import { cn } from "@/lib/utils";
|
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
export type CalendarProps = React.ComponentProps<typeof DayPicker>;
|
export type CalendarProps = React.ComponentProps<typeof DayPicker>;
|
||||||
|
|
||||||
|
|||||||
157
apps/dokploy/drizzle/0076_tough_iron_patriot.sql
Normal file
157
apps/dokploy/drizzle/0076_tough_iron_patriot.sql
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
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 $$;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"id": "27ba0f3d-859f-4233-a179-8aee11ad9179",
|
"id": "7c8508ba-01eb-487e-88cf-0abe10916904",
|
||||||
"prevId": "dd51ff04-a160-4d0d-b72f-4916493b740f",
|
"prevId": "f74127dc-3cda-4091-988f-97b60eb22427",
|
||||||
"version": "7",
|
"version": "7",
|
||||||
"dialect": "postgresql",
|
"dialect": "postgresql",
|
||||||
"tables": {
|
"tables": {
|
||||||
@@ -179,6 +179,13 @@
|
|||||||
"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",
|
||||||
@@ -247,6 +254,43 @@
|
|||||||
"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",
|
||||||
@@ -458,6 +502,12 @@
|
|||||||
"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",
|
||||||
@@ -538,6 +588,19 @@
|
|||||||
"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",
|
||||||
@@ -1703,6 +1766,12 @@
|
|||||||
"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",
|
||||||
@@ -2908,6 +2977,24 @@
|
|||||||
"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",
|
||||||
@@ -3005,6 +3092,12 @@
|
|||||||
"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",
|
||||||
@@ -3079,6 +3172,19 @@
|
|||||||
"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",
|
||||||
@@ -3937,6 +4043,107 @@
|
|||||||
"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": "",
|
||||||
@@ -5001,6 +5208,7 @@
|
|||||||
"github",
|
"github",
|
||||||
"gitlab",
|
"gitlab",
|
||||||
"bitbucket",
|
"bitbucket",
|
||||||
|
"gitea",
|
||||||
"drop"
|
"drop"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -5097,6 +5305,7 @@
|
|||||||
"github",
|
"github",
|
||||||
"gitlab",
|
"gitlab",
|
||||||
"bitbucket",
|
"bitbucket",
|
||||||
|
"gitea",
|
||||||
"raw"
|
"raw"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -5125,7 +5334,8 @@
|
|||||||
"values": [
|
"values": [
|
||||||
"github",
|
"github",
|
||||||
"gitlab",
|
"gitlab",
|
||||||
"bitbucket"
|
"bitbucket",
|
||||||
|
"gitea"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"public.serverStatus": {
|
"public.serverStatus": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"id": "d4d95ab9-16bd-4583-949e-d6ae0a0bb7a0",
|
"id": "c8f3ee9b-66c6-4a23-a151-78e04363bdf9",
|
||||||
"prevId": "27ba0f3d-859f-4233-a179-8aee11ad9179",
|
"prevId": "f74127dc-3cda-4091-988f-97b60eb22427",
|
||||||
"version": "7",
|
"version": "7",
|
||||||
"dialect": "postgresql",
|
"dialect": "postgresql",
|
||||||
"tables": {
|
"tables": {
|
||||||
@@ -179,6 +179,13 @@
|
|||||||
"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",
|
||||||
@@ -247,6 +254,43 @@
|
|||||||
"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",
|
||||||
@@ -458,6 +502,12 @@
|
|||||||
"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",
|
||||||
@@ -538,6 +588,19 @@
|
|||||||
"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",
|
||||||
@@ -2914,6 +2977,24 @@
|
|||||||
"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",
|
||||||
@@ -3011,6 +3092,12 @@
|
|||||||
"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",
|
||||||
@@ -3085,6 +3172,19 @@
|
|||||||
"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",
|
||||||
@@ -3943,6 +4043,107 @@
|
|||||||
"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": "",
|
||||||
@@ -5007,6 +5208,7 @@
|
|||||||
"github",
|
"github",
|
||||||
"gitlab",
|
"gitlab",
|
||||||
"bitbucket",
|
"bitbucket",
|
||||||
|
"gitea",
|
||||||
"drop"
|
"drop"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -5103,6 +5305,7 @@
|
|||||||
"github",
|
"github",
|
||||||
"gitlab",
|
"gitlab",
|
||||||
"bitbucket",
|
"bitbucket",
|
||||||
|
"gitea",
|
||||||
"raw"
|
"raw"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -5131,7 +5334,8 @@
|
|||||||
"values": [
|
"values": [
|
||||||
"github",
|
"github",
|
||||||
"gitlab",
|
"gitlab",
|
||||||
"bitbucket"
|
"bitbucket",
|
||||||
|
"gitea"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"public.serverStatus": {
|
"public.serverStatus": {
|
||||||
|
|||||||
@@ -534,10 +534,31 @@
|
|||||||
"tag": "0075_wild_xorn",
|
"tag": "0075_wild_xorn",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"idx": 76,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1742237840762,
|
||||||
|
"tag": "0076_tough_iron_patriot",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 77,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1742241730000,
|
||||||
|
"tag": "0076_young_sharon_ventura",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"idx": 78,
|
"idx": 78,
|
||||||
"version": "7",
|
"version": "7",
|
||||||
"when": 1742112194375,
|
"when": 1742241730001,
|
||||||
|
"tag": "0077_chemical_dreadnoughts",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 79,
|
||||||
|
"version": "7",
|
||||||
|
"when": 17422417300002,
|
||||||
"tag": "0078_uneven_omega_sentinel",
|
"tag": "0078_uneven_omega_sentinel",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
|
|||||||
552
apps/dokploy/drizzle/meta/_journal.json.backup
Normal file
552
apps/dokploy/drizzle/meta/_journal.json.backup
Normal file
@@ -0,0 +1,552 @@
|
|||||||
|
{
|
||||||
|
"version": "5",
|
||||||
|
"dialect": "pg",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"idx": 0,
|
||||||
|
"version": "5",
|
||||||
|
"when": 1713262741218,
|
||||||
|
"tag": "0000_reflective_puck",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 1,
|
||||||
|
"version": "5",
|
||||||
|
"when": 1713761637676,
|
||||||
|
"tag": "0001_striped_tattoo",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 2,
|
||||||
|
"version": "5",
|
||||||
|
"when": 1713763492341,
|
||||||
|
"tag": "0002_ambiguous_carlie_cooper",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 3,
|
||||||
|
"version": "5",
|
||||||
|
"when": 1713947141424,
|
||||||
|
"tag": "0003_square_lightspeed",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 4,
|
||||||
|
"version": "5",
|
||||||
|
"when": 1714004732716,
|
||||||
|
"tag": "0004_nice_tenebrous",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 5,
|
||||||
|
"version": "5",
|
||||||
|
"when": 1715551130605,
|
||||||
|
"tag": "0005_cute_terror",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 6,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1715563165991,
|
||||||
|
"tag": "0006_oval_jimmy_woo",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 7,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1715563497100,
|
||||||
|
"tag": "0007_cute_guardsmen",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 8,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1715564143641,
|
||||||
|
"tag": "0008_lazy_sage",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 9,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1715564774423,
|
||||||
|
"tag": "0009_majestic_spencer_smythe",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 10,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1715574037832,
|
||||||
|
"tag": "0010_lean_black_widow",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 11,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1715574230599,
|
||||||
|
"tag": "0011_petite_calypso",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 12,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1716015716708,
|
||||||
|
"tag": "0012_chubby_umar",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 13,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1716076179443,
|
||||||
|
"tag": "0013_blushing_starjammers",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 14,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1716715367982,
|
||||||
|
"tag": "0014_same_hammerhead",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 15,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1717564517104,
|
||||||
|
"tag": "0015_fearless_callisto",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 16,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1719109196484,
|
||||||
|
"tag": "0016_chunky_leopardon",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 17,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1719547174326,
|
||||||
|
"tag": "0017_minor_post",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 18,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1719928377858,
|
||||||
|
"tag": "0018_careful_killmonger",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 19,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1721110706912,
|
||||||
|
"tag": "0019_heavy_freak",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 20,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1721363861686,
|
||||||
|
"tag": "0020_fantastic_slapstick",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 21,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1721370423752,
|
||||||
|
"tag": "0021_premium_sebastian_shaw",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 22,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1721531163852,
|
||||||
|
"tag": "0022_warm_colonel_america",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 23,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1721542782659,
|
||||||
|
"tag": "0023_icy_maverick",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 24,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1721603595092,
|
||||||
|
"tag": "0024_dapper_supernaut",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 25,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1721633853118,
|
||||||
|
"tag": "0025_lying_mephisto",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 26,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1721979220929,
|
||||||
|
"tag": "0026_known_dormammu",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 27,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1722445099203,
|
||||||
|
"tag": "0027_red_lady_bullseye",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 28,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1722503439951,
|
||||||
|
"tag": "0028_jittery_eternity",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 29,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1722578386823,
|
||||||
|
"tag": "0029_colossal_zodiak",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 30,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1723608499147,
|
||||||
|
"tag": "0030_little_kabuki",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 31,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1723701656243,
|
||||||
|
"tag": "0031_steep_vulture",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 32,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1723705257806,
|
||||||
|
"tag": "0032_flashy_shadow_king",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 33,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1725250322137,
|
||||||
|
"tag": "0033_white_hawkeye",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 34,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1725256397019,
|
||||||
|
"tag": "0034_aspiring_secret_warriors",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 35,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1725429324584,
|
||||||
|
"tag": "0035_cool_gravity",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 36,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1725519351871,
|
||||||
|
"tag": "0036_tired_ronan",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 37,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1726988289562,
|
||||||
|
"tag": "0037_legal_namor",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 38,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1727942090102,
|
||||||
|
"tag": "0038_rapid_landau",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 39,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1728021127765,
|
||||||
|
"tag": "0039_many_tiger_shark",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 40,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1728780577084,
|
||||||
|
"tag": "0040_graceful_wolfsbane",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 41,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1729667438853,
|
||||||
|
"tag": "0041_huge_bruce_banner",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 42,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1729984439862,
|
||||||
|
"tag": "0042_fancy_havok",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 43,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1731873965888,
|
||||||
|
"tag": "0043_closed_naoko",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 44,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1731875539532,
|
||||||
|
"tag": "0044_sour_true_believers",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 45,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1732644181718,
|
||||||
|
"tag": "0045_smiling_blur",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 46,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1732851191048,
|
||||||
|
"tag": "0046_purple_sleeper",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 47,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1733599090582,
|
||||||
|
"tag": "0047_tidy_revanche",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 48,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1733599163710,
|
||||||
|
"tag": "0048_flat_expediter",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 49,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1733628762978,
|
||||||
|
"tag": "0049_dark_leopardon",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 50,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1733889104203,
|
||||||
|
"tag": "0050_nappy_wrecker",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 51,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1734241482851,
|
||||||
|
"tag": "0051_hard_gorgon",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 52,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1734809337308,
|
||||||
|
"tag": "0052_bumpy_luckman",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 53,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1735118844878,
|
||||||
|
"tag": "0053_broken_kulan_gath",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 54,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1736669421560,
|
||||||
|
"tag": "0054_nervous_spencer_smythe",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 55,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1736669623831,
|
||||||
|
"tag": "0055_next_serpent_society",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 56,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1736789918294,
|
||||||
|
"tag": "0056_majestic_skaar",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 57,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1737306063563,
|
||||||
|
"tag": "0057_tricky_living_tribunal",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 58,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1737612903012,
|
||||||
|
"tag": "0058_brown_sharon_carter",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 59,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1737615160768,
|
||||||
|
"tag": "0059_striped_bill_hollister",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 60,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1737929896838,
|
||||||
|
"tag": "0060_disable-aggressive-cache",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 61,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1738481304953,
|
||||||
|
"tag": "0061_many_molten_man",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 62,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1738482795112,
|
||||||
|
"tag": "0062_slippery_white_tiger",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 63,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1738522845992,
|
||||||
|
"tag": "0063_panoramic_dreadnoughts",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 64,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1738564387043,
|
||||||
|
"tag": "0064_previous_agent_brand",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 65,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1739087857244,
|
||||||
|
"tag": "0065_daily_zaladane",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 66,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1739426913392,
|
||||||
|
"tag": "0066_yielding_echo",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 67,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1740892043121,
|
||||||
|
"tag": "0067_condemned_sugar_man",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 68,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1740897756774,
|
||||||
|
"tag": "0068_complex_rhino",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 69,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1741152916611,
|
||||||
|
"tag": "0069_legal_bill_hollister",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 70,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1741322697251,
|
||||||
|
"tag": "0070_useful_serpent_society",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 71,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1741559743256,
|
||||||
|
"tag": "0071_flimsy_plazm",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 72,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1741593124105,
|
||||||
|
"tag": "0072_low_redwing",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 73,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1741645208694,
|
||||||
|
"tag": "0073_dark_tigra",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 74,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1741673569715,
|
||||||
|
"tag": "0074_military_miss_america",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 75,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1742018928109,
|
||||||
|
"tag": "0075_wild_xorn",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 76,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1742237840762,
|
||||||
|
"tag": "0076_tough_iron_patriot",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 77,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1742238314349,
|
||||||
|
"tag": "0077_mature_tomorrow_man",
|
||||||
|
"breakpoints": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -84,7 +84,7 @@
|
|||||||
"@trpc/client": "^10.43.6",
|
"@trpc/client": "^10.43.6",
|
||||||
"@trpc/next": "^10.43.6",
|
"@trpc/next": "^10.43.6",
|
||||||
"@trpc/react-query": "^10.43.6",
|
"@trpc/react-query": "^10.43.6",
|
||||||
"@trpc/server": "^10.43.6",
|
"@trpc/server": "^10.45.2",
|
||||||
"@uiw/codemirror-theme-github": "^4.22.1",
|
"@uiw/codemirror-theme-github": "^4.22.1",
|
||||||
"@uiw/react-codemirror": "^4.22.1",
|
"@uiw/react-codemirror": "^4.22.1",
|
||||||
"@xterm/addon-attach": "0.10.0",
|
"@xterm/addon-attach": "0.10.0",
|
||||||
@@ -162,7 +162,7 @@
|
|||||||
"@types/js-yaml": "4.0.9",
|
"@types/js-yaml": "4.0.9",
|
||||||
"@types/lodash": "4.17.4",
|
"@types/lodash": "4.17.4",
|
||||||
"@types/micromatch": "4.0.9",
|
"@types/micromatch": "4.0.9",
|
||||||
"@types/node": "^18.17.0",
|
"@types/node": "^18.19.42",
|
||||||
"@types/node-os-utils": "1.3.4",
|
"@types/node-os-utils": "1.3.4",
|
||||||
"@types/node-schedule": "2.1.6",
|
"@types/node-schedule": "2.1.6",
|
||||||
"@types/nodemailer": "^6.4.15",
|
"@types/nodemailer": "^6.4.15",
|
||||||
@@ -197,8 +197,6 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"commitlint": {
|
"commitlint": {
|
||||||
"extends": [
|
"extends": ["@commitlint/config-conventional"]
|
||||||
"@commitlint/config-conventional"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,13 +112,6 @@ export default async function handler(
|
|||||||
res.status(301).json({ message: "Branch Not Match" });
|
res.status(301).json({ message: "Branch Not Match" });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
<<<<<<< HEAD
|
|
||||||
} else if (sourceType === "gitea") {
|
|
||||||
const branchName = extractBranchName(req.headers, req.body);
|
|
||||||
if (!branchName || branchName !== application.giteaBranch) {
|
|
||||||
res.status(301).json({ message: "Branch Not Match" });
|
|
||||||
return;
|
|
||||||
=======
|
|
||||||
|
|
||||||
const commitedPaths = await extractCommitedPaths(
|
const commitedPaths = await extractCommitedPaths(
|
||||||
req.body,
|
req.body,
|
||||||
@@ -134,7 +127,12 @@ export default async function handler(
|
|||||||
if (!shouldDeployPaths) {
|
if (!shouldDeployPaths) {
|
||||||
res.status(301).json({ message: "Watch Paths Not Match" });
|
res.status(301).json({ message: "Watch Paths Not Match" });
|
||||||
return;
|
return;
|
||||||
>>>>>>> fork/canary
|
}
|
||||||
|
} else if (sourceType === "gitea") {
|
||||||
|
const branchName = extractBranchName(req.headers, req.body);
|
||||||
|
if (!branchName || branchName !== application.giteaBranch) {
|
||||||
|
res.status(301).json({ message: "Branch Not Match" });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import { eq } from "drizzle-orm";
|
|||||||
import type { NextApiRequest, NextApiResponse } from "next";
|
import type { NextApiRequest, NextApiResponse } from "next";
|
||||||
import {
|
import {
|
||||||
extractBranchName,
|
extractBranchName,
|
||||||
extractCommitedPaths,
|
|
||||||
extractCommitMessage,
|
extractCommitMessage,
|
||||||
|
extractCommitedPaths,
|
||||||
extractHash,
|
extractHash,
|
||||||
} from "../[refreshToken]";
|
} from "../[refreshToken]";
|
||||||
|
|
||||||
|
|||||||
@@ -1,52 +1,41 @@
|
|||||||
import { NextApiRequest, NextApiResponse } from 'next';
|
import type { NextApiRequest, NextApiResponse } from "next";
|
||||||
import { findGiteaById } from '@dokploy/server';
|
import { findGitea, redirectWithError } from "./helper";
|
||||||
|
|
||||||
export default async function handler(
|
export default async function handler(
|
||||||
req: NextApiRequest,
|
req: NextApiRequest,
|
||||||
res: NextApiResponse
|
res: NextApiResponse,
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
if (req.method !== 'GET') {
|
if (req.method !== "GET") {
|
||||||
return res.status(405).json({ error: 'Method not allowed' });
|
return res.status(405).json({ error: "Method not allowed" });
|
||||||
}
|
}
|
||||||
|
|
||||||
const { giteaId } = req.query;
|
const { giteaId } = req.query;
|
||||||
|
|
||||||
if (!giteaId || Array.isArray(giteaId)) {
|
if (!giteaId || Array.isArray(giteaId)) {
|
||||||
return res.status(400).json({ error: 'Invalid Gitea provider ID' });
|
return res.status(400).json({ error: "Invalid Gitea provider ID" });
|
||||||
}
|
}
|
||||||
|
|
||||||
let gitea;
|
const gitea = await findGitea(giteaId as string);
|
||||||
try {
|
if (!gitea || !gitea.clientId || !gitea.redirectUri) {
|
||||||
gitea = await findGiteaById(giteaId);
|
return redirectWithError(res, "Incomplete OAuth configuration");
|
||||||
} catch (findError) {
|
|
||||||
console.error('Error finding Gitea provider:', findError);
|
|
||||||
return res.status(404).json({ error: 'Failed to find Gitea provider' });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gitea.clientId || !gitea.redirectUri) {
|
// Generate the Gitea authorization URL
|
||||||
return res.status(400).json({
|
|
||||||
error: 'Incomplete OAuth configuration',
|
|
||||||
missingClientId: !gitea.clientId,
|
|
||||||
missingRedirectUri: !gitea.redirectUri
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use the state parameter to pass the giteaId
|
|
||||||
// This is more secure than adding it to the redirect URI
|
|
||||||
const state = giteaId;
|
|
||||||
|
|
||||||
const authorizationUrl = new URL(`${gitea.giteaUrl}/login/oauth/authorize`);
|
const authorizationUrl = new URL(`${gitea.giteaUrl}/login/oauth/authorize`);
|
||||||
authorizationUrl.searchParams.append('client_id', gitea.clientId);
|
authorizationUrl.searchParams.append("client_id", gitea.clientId as string);
|
||||||
authorizationUrl.searchParams.append('response_type', 'code');
|
authorizationUrl.searchParams.append("response_type", "code");
|
||||||
authorizationUrl.searchParams.append('redirect_uri', gitea.redirectUri);
|
authorizationUrl.searchParams.append(
|
||||||
authorizationUrl.searchParams.append('scope', 'read:user repo');
|
"redirect_uri",
|
||||||
authorizationUrl.searchParams.append('state', state);
|
gitea.redirectUri as string,
|
||||||
|
);
|
||||||
|
authorizationUrl.searchParams.append("scope", "read:user repo");
|
||||||
|
authorizationUrl.searchParams.append("state", giteaId as string);
|
||||||
|
|
||||||
// Redirect the user to the Gitea authorization page
|
// Redirect user to Gitea authorization URL
|
||||||
res.redirect(307, authorizationUrl.toString());
|
return res.redirect(307, authorizationUrl.toString());
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error initiating Gitea OAuth flow:', error);
|
console.error("Error initiating Gitea OAuth flow:", error);
|
||||||
return res.status(500).json({ error: 'Internal server error' });
|
return res.status(500).json({ error: "Internal server error" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,148 +1,71 @@
|
|||||||
import { NextApiRequest, NextApiResponse } from 'next';
|
import { updateGitea } from "@dokploy/server";
|
||||||
import { findGiteaById, updateGitea } from '@dokploy/server';
|
import type { NextApiRequest, NextApiResponse } from "next";
|
||||||
|
import { type Gitea, findGitea, redirectWithError } from "./helper";
|
||||||
|
|
||||||
export default async function handler(
|
// Helper to parse the state parameter
|
||||||
req: NextApiRequest,
|
const parseState = (state: string): string | null => {
|
||||||
res: NextApiResponse
|
|
||||||
) {
|
|
||||||
try {
|
try {
|
||||||
console.log('Full Callback Request:', {
|
const stateObj =
|
||||||
query: req.query,
|
state.startsWith("{") && state.endsWith("}") ? JSON.parse(state) : {};
|
||||||
method: req.method,
|
return stateObj.giteaId || state || null;
|
||||||
timestamp: new Date().toISOString()
|
} catch {
|
||||||
});
|
return null;
|
||||||
|
|
||||||
const { code, state } = req.query;
|
|
||||||
|
|
||||||
// Verify received parameters
|
|
||||||
console.log('Received Parameters:', {
|
|
||||||
code: code ? 'Present' : 'Missing',
|
|
||||||
state: state ? 'Present' : 'Missing'
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!code || Array.isArray(code)) {
|
|
||||||
console.error('Invalid code:', code);
|
|
||||||
return res.redirect(
|
|
||||||
307,
|
|
||||||
`/dashboard/settings/git-providers?error=${encodeURIComponent('Invalid authorization code')}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The state parameter now contains the giteaId
|
|
||||||
if (!state || Array.isArray(state)) {
|
|
||||||
console.error('Invalid state parameter:', state);
|
|
||||||
return res.redirect(
|
|
||||||
307,
|
|
||||||
`/dashboard/settings/git-providers?error=${encodeURIComponent('Invalid state parameter')}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract the giteaId from the state parameter
|
|
||||||
let giteaId: string;
|
|
||||||
try {
|
|
||||||
// The state could be a simple string or a JSON object
|
|
||||||
if (state.startsWith('{') && state.endsWith('}')) {
|
|
||||||
const stateObj = JSON.parse(state);
|
|
||||||
giteaId = stateObj.giteaId;
|
|
||||||
} else {
|
|
||||||
giteaId = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!giteaId) {
|
|
||||||
throw new Error('giteaId not found in state parameter');
|
|
||||||
}
|
|
||||||
} catch (parseError) {
|
|
||||||
console.error('Error parsing state parameter:', parseError);
|
|
||||||
return res.redirect(
|
|
||||||
307,
|
|
||||||
`/dashboard/settings/git-providers?error=${encodeURIComponent('Invalid state format')}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let gitea;
|
|
||||||
try {
|
|
||||||
gitea = await findGiteaById(giteaId);
|
|
||||||
} catch (findError) {
|
|
||||||
console.error('Error finding Gitea provider:', findError);
|
|
||||||
return res.redirect(
|
|
||||||
307,
|
|
||||||
`/dashboard/settings/git-providers?error=${encodeURIComponent('Failed to find Gitea provider')}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extensive logging of Gitea provider details
|
|
||||||
console.log('Gitea Provider Details:', {
|
|
||||||
id: gitea.giteaId,
|
|
||||||
url: gitea.giteaUrl,
|
|
||||||
clientId: gitea.clientId ? 'Present' : 'Missing',
|
|
||||||
clientSecret: gitea.clientSecret ? 'Present' : 'Missing',
|
|
||||||
redirectUri: gitea.redirectUri
|
|
||||||
});
|
|
||||||
|
|
||||||
// Validate required OAuth parameters
|
|
||||||
if (!gitea.clientId || !gitea.clientSecret) {
|
|
||||||
console.error('Missing OAuth configuration:', {
|
|
||||||
hasClientId: !!gitea.clientId,
|
|
||||||
hasClientSecret: !!gitea.clientSecret
|
|
||||||
});
|
|
||||||
return res.redirect(
|
|
||||||
307,
|
|
||||||
`/dashboard/settings/git-providers?error=${encodeURIComponent('Incomplete OAuth configuration')}`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper to fetch access token from Gitea
|
||||||
|
const fetchAccessToken = async (gitea: Gitea, code: string) => {
|
||||||
const response = await fetch(`${gitea.giteaUrl}/login/oauth/access_token`, {
|
const response = await fetch(`${gitea.giteaUrl}/login/oauth/access_token`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/x-www-form-urlencoded",
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
"Accept": "application/json",
|
Accept: "application/json",
|
||||||
},
|
},
|
||||||
body: new URLSearchParams({
|
body: new URLSearchParams({
|
||||||
client_id: gitea.clientId as string,
|
client_id: gitea.clientId as string,
|
||||||
client_secret: gitea.clientSecret as string,
|
client_secret: gitea.clientSecret as string,
|
||||||
code: code as string,
|
code,
|
||||||
grant_type: "authorization_code",
|
grant_type: "authorization_code",
|
||||||
redirect_uri: gitea.redirectUri || '',
|
redirect_uri: gitea.redirectUri || "",
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Log raw response details
|
|
||||||
const responseText = await response.text();
|
const responseText = await response.text();
|
||||||
|
return response.ok
|
||||||
|
? JSON.parse(responseText)
|
||||||
|
: { error: "Token exchange failed", responseText };
|
||||||
|
};
|
||||||
|
|
||||||
let result;
|
export default async function handler(
|
||||||
try {
|
req: NextApiRequest,
|
||||||
result = JSON.parse(responseText);
|
res: NextApiResponse,
|
||||||
} catch (parseError) {
|
) {
|
||||||
console.error('Failed to parse response:', {
|
const { code, state } = req.query;
|
||||||
error: parseError,
|
|
||||||
responseText
|
if (!code || Array.isArray(code) || !state || Array.isArray(state)) {
|
||||||
});
|
return redirectWithError(
|
||||||
return res.redirect(
|
res,
|
||||||
307,
|
"Invalid authorization code or state parameter",
|
||||||
`/dashboard/settings/git-providers?error=${encodeURIComponent('Failed to parse token response')}`
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!response.ok) {
|
const giteaId = parseState(state as string);
|
||||||
console.error('Gitea token exchange failed:', {
|
if (!giteaId) return redirectWithError(res, "Invalid state format");
|
||||||
result,
|
|
||||||
responseStatus: response.status
|
const gitea = await findGitea(giteaId);
|
||||||
});
|
if (!gitea) return redirectWithError(res, "Failed to find Gitea provider");
|
||||||
return res.redirect(
|
|
||||||
307,
|
// Fetch the access token from Gitea
|
||||||
`/dashboard/settings/git-providers?error=${encodeURIComponent(result.error || 'Token exchange failed')}`
|
const result = await fetchAccessToken(gitea, code as string);
|
||||||
);
|
|
||||||
|
if (result.error) {
|
||||||
|
console.error("Token exchange failed:", result);
|
||||||
|
return redirectWithError(res, result.error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate token response
|
|
||||||
if (!result.access_token) {
|
if (!result.access_token) {
|
||||||
console.error('Missing access token in response:', {
|
console.error("Missing access token:", result);
|
||||||
fullResponse: result
|
return redirectWithError(res, "No access token received");
|
||||||
});
|
|
||||||
return res.redirect(
|
|
||||||
307,
|
|
||||||
`/dashboard/settings/git-providers?error=${encodeURIComponent('No access token received')}`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const expiresAt = result.expires_in
|
const expiresAt = result.expires_in
|
||||||
@@ -150,37 +73,22 @@ export default async function handler(
|
|||||||
: null;
|
: null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Perform the update
|
|
||||||
const updatedGitea = await updateGitea(gitea.giteaId, {
|
const updatedGitea = await updateGitea(gitea.giteaId, {
|
||||||
accessToken: result.access_token,
|
accessToken: result.access_token,
|
||||||
refreshToken: result.refresh_token,
|
refreshToken: result.refresh_token,
|
||||||
expiresAt,
|
expiresAt,
|
||||||
...(result.organizationName ? { organizationName: result.organizationName } : {}),
|
...(result.organizationName
|
||||||
|
? { organizationName: result.organizationName }
|
||||||
|
: {}),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Log successful update
|
console.log("Gitea provider updated successfully:", updatedGitea);
|
||||||
console.log('Gitea provider updated successfully:', {
|
return res.redirect(
|
||||||
hasAccessToken: !!updatedGitea.accessToken,
|
307,
|
||||||
hasRefreshToken: !!updatedGitea.refreshToken,
|
"/dashboard/settings/git-providers?connected=true",
|
||||||
expiresAt: updatedGitea.expiresAt
|
);
|
||||||
});
|
|
||||||
|
|
||||||
return res.redirect(307, "/dashboard/settings/git-providers?connected=true");
|
|
||||||
} catch (updateError) {
|
} catch (updateError) {
|
||||||
console.error('Failed to update Gitea provider:', {
|
console.error("Failed to update Gitea provider:", updateError);
|
||||||
error: updateError,
|
return redirectWithError(res, "Failed to store access token");
|
||||||
giteaId: gitea.giteaId
|
|
||||||
});
|
|
||||||
return res.redirect(
|
|
||||||
307,
|
|
||||||
`/dashboard/settings/git-providers?error=${encodeURIComponent('Failed to store access token')}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Comprehensive Callback Error:', error);
|
|
||||||
return res.redirect(
|
|
||||||
307,
|
|
||||||
`/dashboard/settings/git-providers?error=${encodeURIComponent('Internal server error')}`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
42
apps/dokploy/pages/api/providers/gitea/helper.ts
Normal file
42
apps/dokploy/pages/api/providers/gitea/helper.ts
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import { findGiteaById } from "@dokploy/server";
|
||||||
|
import type { NextApiResponse } from "next";
|
||||||
|
|
||||||
|
// Shared Gitea interface
|
||||||
|
export interface Gitea {
|
||||||
|
giteaId: string;
|
||||||
|
gitProviderId: string;
|
||||||
|
redirectUri: string | null;
|
||||||
|
accessToken: string | null;
|
||||||
|
refreshToken: string | null;
|
||||||
|
expiresAt: number | null;
|
||||||
|
giteaUrl: string;
|
||||||
|
clientId: string | null;
|
||||||
|
clientSecret: string | null;
|
||||||
|
organizationName?: string;
|
||||||
|
gitProvider: {
|
||||||
|
name: string;
|
||||||
|
gitProviderId: string;
|
||||||
|
providerType: "github" | "gitlab" | "bitbucket" | "gitea";
|
||||||
|
createdAt: string;
|
||||||
|
organizationId: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shared function to find Gitea by ID
|
||||||
|
export const findGitea = async (giteaId: string): Promise<Gitea | null> => {
|
||||||
|
try {
|
||||||
|
const gitea = await findGiteaById(giteaId);
|
||||||
|
return gitea;
|
||||||
|
} catch (findError) {
|
||||||
|
console.error("Error finding Gitea provider:", findError);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper for redirecting with error message
|
||||||
|
export const redirectWithError = (res: NextApiResponse, error: string) => {
|
||||||
|
return res.redirect(
|
||||||
|
307,
|
||||||
|
`/dashboard/settings/git-providers?error=${encodeURIComponent(error)}`,
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -34,6 +34,15 @@ import {
|
|||||||
CommandInput,
|
CommandInput,
|
||||||
CommandItem,
|
CommandItem,
|
||||||
} from "@/components/ui/command";
|
} from "@/components/ui/command";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
DropdownMenuContent,
|
DropdownMenuContent,
|
||||||
@@ -47,6 +56,13 @@ import {
|
|||||||
PopoverContent,
|
PopoverContent,
|
||||||
PopoverTrigger,
|
PopoverTrigger,
|
||||||
} from "@/components/ui/popover";
|
} from "@/components/ui/popover";
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from "@/components/ui/select";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { appRouter } from "@/server/api/root";
|
import { appRouter } from "@/server/api/root";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
@@ -64,8 +80,8 @@ import {
|
|||||||
Loader2,
|
Loader2,
|
||||||
PlusIcon,
|
PlusIcon,
|
||||||
Search,
|
Search,
|
||||||
X,
|
|
||||||
Trash2,
|
Trash2,
|
||||||
|
X,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import type {
|
import type {
|
||||||
GetServerSidePropsContext,
|
GetServerSidePropsContext,
|
||||||
@@ -73,25 +89,9 @@ import type {
|
|||||||
} from "next";
|
} from "next";
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { type ReactElement, useMemo, useState, useEffect } from "react";
|
import { type ReactElement, useEffect, useMemo, useState } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import superjson from "superjson";
|
import superjson from "superjson";
|
||||||
import {
|
|
||||||
Dialog,
|
|
||||||
DialogContent,
|
|
||||||
DialogDescription,
|
|
||||||
DialogFooter,
|
|
||||||
DialogHeader,
|
|
||||||
DialogTitle,
|
|
||||||
DialogTrigger,
|
|
||||||
} from "@/components/ui/dialog";
|
|
||||||
import {
|
|
||||||
Select,
|
|
||||||
SelectContent,
|
|
||||||
SelectItem,
|
|
||||||
SelectTrigger,
|
|
||||||
SelectValue,
|
|
||||||
} from "@/components/ui/select";
|
|
||||||
|
|
||||||
export type Services = {
|
export type Services = {
|
||||||
appName: string;
|
appName: string;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { ShowImport } from "@/components/dashboard/application/advanced/import/show-import";
|
||||||
import { ShowVolumes } from "@/components/dashboard/application/advanced/volumes/show-volumes";
|
import { ShowVolumes } from "@/components/dashboard/application/advanced/volumes/show-volumes";
|
||||||
import { ShowEnvironment } from "@/components/dashboard/application/environment/show-enviroment";
|
import { ShowEnvironment } from "@/components/dashboard/application/environment/show-enviroment";
|
||||||
import { AddCommandCompose } from "@/components/dashboard/compose/advanced/add-command";
|
import { AddCommandCompose } from "@/components/dashboard/compose/advanced/add-command";
|
||||||
@@ -47,7 +48,6 @@ import { useRouter } from "next/router";
|
|||||||
import { type ReactElement, useEffect, useState } from "react";
|
import { type ReactElement, useEffect, useState } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import superjson from "superjson";
|
import superjson from "superjson";
|
||||||
import { ShowImport } from "@/components/dashboard/application/advanced/import/show-import";
|
|
||||||
|
|
||||||
type TabState =
|
type TabState =
|
||||||
| "projects"
|
| "projects"
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ import { ShowExternalPostgresCredentials } from "@/components/dashboard/postgres
|
|||||||
import { ShowGeneralPostgres } from "@/components/dashboard/postgres/general/show-general-postgres";
|
import { ShowGeneralPostgres } from "@/components/dashboard/postgres/general/show-general-postgres";
|
||||||
import { ShowInternalPostgresCredentials } from "@/components/dashboard/postgres/general/show-internal-postgres-credentials";
|
import { ShowInternalPostgresCredentials } from "@/components/dashboard/postgres/general/show-internal-postgres-credentials";
|
||||||
import { UpdatePostgres } from "@/components/dashboard/postgres/update-postgres";
|
import { UpdatePostgres } from "@/components/dashboard/postgres/update-postgres";
|
||||||
|
import { ShowDatabaseAdvancedSettings } from "@/components/dashboard/shared/show-database-advanced-settings";
|
||||||
import { PostgresqlIcon } from "@/components/icons/data-tools-icons";
|
import { PostgresqlIcon } from "@/components/icons/data-tools-icons";
|
||||||
import { ProjectLayout } from "@/components/layouts/project-layout";
|
import { ProjectLayout } from "@/components/layouts/project-layout";
|
||||||
import { BreadcrumbSidebar } from "@/components/shared/breadcrumb-sidebar";
|
import { BreadcrumbSidebar } from "@/components/shared/breadcrumb-sidebar";
|
||||||
import { StatusTooltip } from "@/components/shared/status-tooltip";
|
import { StatusTooltip } from "@/components/shared/status-tooltip";
|
||||||
import { ShowDatabaseAdvancedSettings } from "@/components/dashboard/shared/show-database-advanced-settings";
|
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { getLocale, serverSideTranslations } from "@/utils/i18n";
|
|||||||
import { validateRequest } from "@dokploy/server";
|
import { validateRequest } from "@dokploy/server";
|
||||||
import { createServerSideHelpers } from "@trpc/react-query/server";
|
import { createServerSideHelpers } from "@trpc/react-query/server";
|
||||||
import type { GetServerSidePropsContext } from "next";
|
import type { GetServerSidePropsContext } from "next";
|
||||||
import React, { type ReactElement } from "react";
|
import type { ReactElement } from "react";
|
||||||
import superjson from "superjson";
|
import superjson from "superjson";
|
||||||
|
|
||||||
const Page = () => {
|
const Page = () => {
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ import { destinationRouter } from "./routers/destination";
|
|||||||
import { dockerRouter } from "./routers/docker";
|
import { dockerRouter } from "./routers/docker";
|
||||||
import { domainRouter } from "./routers/domain";
|
import { domainRouter } from "./routers/domain";
|
||||||
import { gitProviderRouter } from "./routers/git-provider";
|
import { gitProviderRouter } from "./routers/git-provider";
|
||||||
|
import { giteaRouter } from "./routers/gitea";
|
||||||
import { githubRouter } from "./routers/github";
|
import { githubRouter } from "./routers/github";
|
||||||
import { gitlabRouter } from "./routers/gitlab";
|
import { gitlabRouter } from "./routers/gitlab";
|
||||||
import { giteaRouter } from "./routers/gitea";
|
|
||||||
import { mariadbRouter } from "./routers/mariadb";
|
import { mariadbRouter } from "./routers/mariadb";
|
||||||
import { mongoRouter } from "./routers/mongo";
|
import { mongoRouter } from "./routers/mongo";
|
||||||
import { mountRouter } from "./routers/mount";
|
import { mountRouter } from "./routers/mount";
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ import {
|
|||||||
checkServiceAccess,
|
checkServiceAccess,
|
||||||
} from "@dokploy/server/services/user";
|
} from "@dokploy/server/services/user";
|
||||||
import {
|
import {
|
||||||
getProviderHeaders,
|
|
||||||
type Model,
|
type Model,
|
||||||
|
getProviderHeaders,
|
||||||
} from "@dokploy/server/utils/ai/select-ai-provider";
|
} from "@dokploy/server/utils/ai/select-ai-provider";
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ import {
|
|||||||
apiSaveDockerProvider,
|
apiSaveDockerProvider,
|
||||||
apiSaveEnvironmentVariables,
|
apiSaveEnvironmentVariables,
|
||||||
apiSaveGitProvider,
|
apiSaveGitProvider,
|
||||||
|
apiSaveGiteaProvider,
|
||||||
apiSaveGithubProvider,
|
apiSaveGithubProvider,
|
||||||
apiSaveGitlabProvider,
|
apiSaveGitlabProvider,
|
||||||
apiSaveGiteaProvider,
|
|
||||||
apiUpdateApplication,
|
apiUpdateApplication,
|
||||||
applications,
|
applications,
|
||||||
} from "@/server/db/schema";
|
} from "@/server/db/schema";
|
||||||
|
|||||||
@@ -9,23 +9,10 @@ import {
|
|||||||
apiUpdateCompose,
|
apiUpdateCompose,
|
||||||
compose as composeTable,
|
compose as composeTable,
|
||||||
} from "@/server/db/schema";
|
} from "@/server/db/schema";
|
||||||
import { cleanQueuesByCompose, myQueue } from "@/server/queues/queueSetup";
|
|
||||||
import { generatePassword } from "@/templates/utils";
|
|
||||||
import {
|
|
||||||
type CompleteTemplate,
|
|
||||||
fetchTemplateFiles,
|
|
||||||
fetchTemplatesList,
|
|
||||||
} from "@dokploy/server/templates/github";
|
|
||||||
import { processTemplate } from "@dokploy/server/templates/processors";
|
|
||||||
import { TRPCError } from "@trpc/server";
|
|
||||||
import { eq } from "drizzle-orm";
|
|
||||||
import { dump, load } from "js-yaml";
|
|
||||||
import _ from "lodash";
|
|
||||||
import { nanoid } from "nanoid";
|
|
||||||
import { createTRPCRouter, protectedProcedure, publicProcedure } from "../trpc";
|
|
||||||
import { z } from "zod";
|
|
||||||
import type { DeploymentJob } from "@/server/queues/queue-types";
|
import type { DeploymentJob } from "@/server/queues/queue-types";
|
||||||
|
import { cleanQueuesByCompose, myQueue } from "@/server/queues/queueSetup";
|
||||||
import { deploy } from "@/server/utils/deploy";
|
import { deploy } from "@/server/utils/deploy";
|
||||||
|
import { generatePassword } from "@/templates/utils";
|
||||||
import {
|
import {
|
||||||
IS_CLOUD,
|
IS_CLOUD,
|
||||||
addDomainToCompose,
|
addDomainToCompose,
|
||||||
@@ -55,6 +42,19 @@ import {
|
|||||||
stopCompose,
|
stopCompose,
|
||||||
updateCompose,
|
updateCompose,
|
||||||
} from "@dokploy/server";
|
} from "@dokploy/server";
|
||||||
|
import {
|
||||||
|
type CompleteTemplate,
|
||||||
|
fetchTemplateFiles,
|
||||||
|
fetchTemplatesList,
|
||||||
|
} from "@dokploy/server/templates/github";
|
||||||
|
import { processTemplate } from "@dokploy/server/templates/processors";
|
||||||
|
import { TRPCError } from "@trpc/server";
|
||||||
|
import { eq } from "drizzle-orm";
|
||||||
|
import { dump, load } from "js-yaml";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { nanoid } from "nanoid";
|
||||||
|
import { z } from "zod";
|
||||||
|
import { createTRPCRouter, protectedProcedure, publicProcedure } from "../trpc";
|
||||||
|
|
||||||
export const composeRouter = createTRPCRouter({
|
export const composeRouter = createTRPCRouter({
|
||||||
create: protectedProcedure
|
create: protectedProcedure
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import {
|
|||||||
updateDestinationById,
|
updateDestinationById,
|
||||||
} from "@dokploy/server";
|
} from "@dokploy/server";
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
import { eq, desc } from "drizzle-orm";
|
import { desc, eq } from "drizzle-orm";
|
||||||
|
|
||||||
export const destinationRouter = createTRPCRouter({
|
export const destinationRouter = createTRPCRouter({
|
||||||
create: adminProcedure
|
create: adminProcedure
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc";
|
import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc";
|
||||||
import {
|
import {
|
||||||
apiCreateGitea,
|
apiCreateGitea,
|
||||||
|
apiFindGiteaBranches,
|
||||||
apiFindOneGitea,
|
apiFindOneGitea,
|
||||||
apiGiteaTestConnection,
|
apiGiteaTestConnection,
|
||||||
apiUpdateGitea,
|
apiUpdateGitea,
|
||||||
apiFindGiteaBranches,
|
|
||||||
} from "@/server/db/schema";
|
} from "@/server/db/schema";
|
||||||
|
|
||||||
import { db } from "@/server/db";
|
import { db } from "@/server/db";
|
||||||
import {
|
import {
|
||||||
createGitea,
|
createGitea,
|
||||||
findGiteaById,
|
findGiteaById,
|
||||||
|
getGiteaBranches,
|
||||||
|
getGiteaRepositories,
|
||||||
haveGiteaRequirements,
|
haveGiteaRequirements,
|
||||||
testGiteaConnection,
|
testGiteaConnection,
|
||||||
updateGitProvider,
|
updateGitProvider,
|
||||||
updateGitea,
|
updateGitea,
|
||||||
getGiteaBranches,
|
|
||||||
getGiteaRepositories,
|
|
||||||
} from "@dokploy/server";
|
} from "@dokploy/server";
|
||||||
|
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
@@ -66,7 +66,8 @@ export const giteaRouter = createTRPCRouter({
|
|||||||
// Filter by organization ID
|
// Filter by organization ID
|
||||||
result = result.filter(
|
result = result.filter(
|
||||||
(provider) =>
|
(provider) =>
|
||||||
provider.gitProvider.organizationId === ctx.session.activeOrganizationId
|
provider.gitProvider.organizationId ===
|
||||||
|
ctx.session.activeOrganizationId,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Filter providers that meet the requirements
|
// Filter providers that meet the requirements
|
||||||
@@ -110,10 +111,10 @@ export const giteaRouter = createTRPCRouter({
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Call the service layer function to get repositories
|
// Call the service layer function to get repositories
|
||||||
console.log('Calling getGiteaRepositories with giteaId:', giteaId);
|
console.log("Calling getGiteaRepositories with giteaId:", giteaId);
|
||||||
return await getGiteaRepositories(giteaId);
|
return await getGiteaRepositories(giteaId);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching Gitea repositories:', error);
|
console.error("Error fetching Gitea repositories:", error);
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "BAD_REQUEST",
|
code: "BAD_REQUEST",
|
||||||
message: error instanceof Error ? error.message : String(error),
|
message: error instanceof Error ? error.message : String(error),
|
||||||
@@ -130,7 +131,8 @@ export const giteaRouter = createTRPCRouter({
|
|||||||
if (!giteaId || !owner || !repositoryName) {
|
if (!giteaId || !owner || !repositoryName) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "BAD_REQUEST",
|
code: "BAD_REQUEST",
|
||||||
message: "Gitea provider ID, owner, and repository name are required.",
|
message:
|
||||||
|
"Gitea provider ID, owner, and repository name are required.",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,20 +149,20 @@ export const giteaRouter = createTRPCRouter({
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Call the service layer function with the required parameters
|
// Call the service layer function with the required parameters
|
||||||
console.log('Calling getGiteaBranches with:', {
|
console.log("Calling getGiteaBranches with:", {
|
||||||
giteaId,
|
giteaId,
|
||||||
owner,
|
owner,
|
||||||
repo: repositoryName
|
repo: repositoryName,
|
||||||
});
|
});
|
||||||
|
|
||||||
return await getGiteaBranches({
|
return await getGiteaBranches({
|
||||||
giteaId,
|
giteaId,
|
||||||
owner,
|
owner,
|
||||||
repo: repositoryName,
|
repo: repositoryName,
|
||||||
id: 0 // Provide a default value for the optional id
|
id: 0, // Provide a default value for the optional id
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching Gitea branches:', error);
|
console.error("Error fetching Gitea branches:", error);
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "BAD_REQUEST",
|
code: "BAD_REQUEST",
|
||||||
message: error instanceof Error ? error.message : String(error),
|
message: error instanceof Error ? error.message : String(error),
|
||||||
@@ -173,7 +175,7 @@ export const giteaRouter = createTRPCRouter({
|
|||||||
.input(apiGiteaTestConnection)
|
.input(apiGiteaTestConnection)
|
||||||
.mutation(async ({ input, ctx }) => {
|
.mutation(async ({ input, ctx }) => {
|
||||||
// Ensure giteaId is always a non-empty string
|
// Ensure giteaId is always a non-empty string
|
||||||
const giteaId = input.giteaId ?? '';
|
const giteaId = input.giteaId ?? "";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const giteaProvider = await findGiteaById(giteaId);
|
const giteaProvider = await findGiteaById(giteaId);
|
||||||
@@ -193,7 +195,7 @@ export const giteaRouter = createTRPCRouter({
|
|||||||
|
|
||||||
return `Found ${result} repositories`;
|
return `Found ${result} repositories`;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Gitea connection test error:', error);
|
console.error("Gitea connection test error:", error);
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "BAD_REQUEST",
|
code: "BAD_REQUEST",
|
||||||
message: error instanceof Error ? error.message : String(error),
|
message: error instanceof Error ? error.message : String(error),
|
||||||
@@ -216,7 +218,7 @@ export const giteaRouter = createTRPCRouter({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Updating Gitea provider:', input);
|
console.log("Updating Gitea provider:", input);
|
||||||
|
|
||||||
if (input.name) {
|
if (input.name) {
|
||||||
await updateGitProvider(input.gitProviderId, {
|
await updateGitProvider(input.gitProviderId, {
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc";
|
import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc";
|
||||||
|
import { db } from "@/server/db";
|
||||||
import {
|
import {
|
||||||
apiChangeMariaDBStatus,
|
apiChangeMariaDBStatus,
|
||||||
apiCreateMariaDB,
|
apiCreateMariaDB,
|
||||||
apiDeployMariaDB,
|
apiDeployMariaDB,
|
||||||
apiFindOneMariaDB,
|
apiFindOneMariaDB,
|
||||||
|
apiRebuildMariadb,
|
||||||
apiResetMariadb,
|
apiResetMariadb,
|
||||||
apiSaveEnvironmentVariablesMariaDB,
|
apiSaveEnvironmentVariablesMariaDB,
|
||||||
apiSaveExternalPortMariaDB,
|
apiSaveExternalPortMariaDB,
|
||||||
apiUpdateMariaDB,
|
apiUpdateMariaDB,
|
||||||
apiRebuildMariadb,
|
|
||||||
mariadb as mariadbTable,
|
mariadb as mariadbTable,
|
||||||
} from "@/server/db/schema";
|
} from "@/server/db/schema";
|
||||||
import { cancelJobs } from "@/server/utils/backup";
|
import { cancelJobs } from "@/server/utils/backup";
|
||||||
@@ -30,12 +31,11 @@ import {
|
|||||||
stopServiceRemote,
|
stopServiceRemote,
|
||||||
updateMariadbById,
|
updateMariadbById,
|
||||||
} from "@dokploy/server";
|
} from "@dokploy/server";
|
||||||
|
import { rebuildDatabase } from "@dokploy/server";
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
import { observable } from "@trpc/server/observable";
|
import { observable } from "@trpc/server/observable";
|
||||||
import { z } from "zod";
|
|
||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
import { db } from "@/server/db";
|
import { z } from "zod";
|
||||||
import { rebuildDatabase } from "@dokploy/server";
|
|
||||||
export const mariadbRouter = createTRPCRouter({
|
export const mariadbRouter = createTRPCRouter({
|
||||||
create: protectedProcedure
|
create: protectedProcedure
|
||||||
.input(apiCreateMariaDB)
|
.input(apiCreateMariaDB)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc";
|
import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc";
|
||||||
|
import { db } from "@/server/db";
|
||||||
import {
|
import {
|
||||||
apiChangeMongoStatus,
|
apiChangeMongoStatus,
|
||||||
apiCreateMongo,
|
apiCreateMongo,
|
||||||
@@ -30,12 +31,11 @@ import {
|
|||||||
stopServiceRemote,
|
stopServiceRemote,
|
||||||
updateMongoById,
|
updateMongoById,
|
||||||
} from "@dokploy/server";
|
} from "@dokploy/server";
|
||||||
|
import { rebuildDatabase } from "@dokploy/server";
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
import { observable } from "@trpc/server/observable";
|
import { observable } from "@trpc/server/observable";
|
||||||
import { z } from "zod";
|
|
||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
import { db } from "@/server/db";
|
import { z } from "zod";
|
||||||
import { rebuildDatabase } from "@dokploy/server";
|
|
||||||
export const mongoRouter = createTRPCRouter({
|
export const mongoRouter = createTRPCRouter({
|
||||||
create: protectedProcedure
|
create: protectedProcedure
|
||||||
.input(apiCreateMongo)
|
.input(apiCreateMongo)
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
|
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
|
|
||||||
|
import { db } from "@/server/db";
|
||||||
import { cancelJobs } from "@/server/utils/backup";
|
import { cancelJobs } from "@/server/utils/backup";
|
||||||
import {
|
import {
|
||||||
IS_CLOUD,
|
IS_CLOUD,
|
||||||
@@ -36,7 +37,6 @@ import {
|
|||||||
} from "@dokploy/server";
|
} from "@dokploy/server";
|
||||||
import { observable } from "@trpc/server/observable";
|
import { observable } from "@trpc/server/observable";
|
||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
import { db } from "@/server/db";
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
export const mysqlRouter = createTRPCRouter({
|
export const mysqlRouter = createTRPCRouter({
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc";
|
import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc";
|
||||||
|
import { db } from "@/server/db";
|
||||||
import {
|
import {
|
||||||
apiChangePostgresStatus,
|
apiChangePostgresStatus,
|
||||||
apiCreatePostgres,
|
apiCreatePostgres,
|
||||||
@@ -33,9 +34,8 @@ import {
|
|||||||
} from "@dokploy/server";
|
} from "@dokploy/server";
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
import { observable } from "@trpc/server/observable";
|
import { observable } from "@trpc/server/observable";
|
||||||
import { z } from "zod";
|
|
||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
import { db } from "@/server/db";
|
import { z } from "zod";
|
||||||
export const postgresRouter = createTRPCRouter({
|
export const postgresRouter = createTRPCRouter({
|
||||||
create: protectedProcedure
|
create: protectedProcedure
|
||||||
.input(apiCreatePostgres)
|
.input(apiCreatePostgres)
|
||||||
|
|||||||
@@ -4,16 +4,17 @@ import {
|
|||||||
apiCreateRedis,
|
apiCreateRedis,
|
||||||
apiDeployRedis,
|
apiDeployRedis,
|
||||||
apiFindOneRedis,
|
apiFindOneRedis,
|
||||||
|
apiRebuildRedis,
|
||||||
apiResetRedis,
|
apiResetRedis,
|
||||||
apiSaveEnvironmentVariablesRedis,
|
apiSaveEnvironmentVariablesRedis,
|
||||||
apiSaveExternalPortRedis,
|
apiSaveExternalPortRedis,
|
||||||
apiUpdateRedis,
|
apiUpdateRedis,
|
||||||
redis as redisTable,
|
redis as redisTable,
|
||||||
apiRebuildRedis,
|
|
||||||
} from "@/server/db/schema";
|
} from "@/server/db/schema";
|
||||||
|
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
|
|
||||||
|
import { db } from "@/server/db";
|
||||||
import {
|
import {
|
||||||
IS_CLOUD,
|
IS_CLOUD,
|
||||||
addNewService,
|
addNewService,
|
||||||
@@ -31,11 +32,10 @@ import {
|
|||||||
stopServiceRemote,
|
stopServiceRemote,
|
||||||
updateRedisById,
|
updateRedisById,
|
||||||
} from "@dokploy/server";
|
} from "@dokploy/server";
|
||||||
|
import { rebuildDatabase } from "@dokploy/server";
|
||||||
import { observable } from "@trpc/server/observable";
|
import { observable } from "@trpc/server/observable";
|
||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
import { db } from "@/server/db";
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { rebuildDatabase } from "@dokploy/server";
|
|
||||||
export const redisRouter = createTRPCRouter({
|
export const redisRouter = createTRPCRouter({
|
||||||
create: protectedProcedure
|
create: protectedProcedure
|
||||||
.input(apiCreateRedis)
|
.input(apiCreateRedis)
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import {
|
|||||||
findUserById,
|
findUserById,
|
||||||
getDokployImage,
|
getDokployImage,
|
||||||
getDokployImageTag,
|
getDokployImageTag,
|
||||||
|
getLogCleanupStatus,
|
||||||
getUpdateData,
|
getUpdateData,
|
||||||
initializeTraefik,
|
initializeTraefik,
|
||||||
parseRawConfig,
|
parseRawConfig,
|
||||||
@@ -41,6 +42,8 @@ import {
|
|||||||
recreateDirectory,
|
recreateDirectory,
|
||||||
sendDockerCleanupNotifications,
|
sendDockerCleanupNotifications,
|
||||||
spawnAsync,
|
spawnAsync,
|
||||||
|
startLogCleanup,
|
||||||
|
stopLogCleanup,
|
||||||
updateLetsEncryptEmail,
|
updateLetsEncryptEmail,
|
||||||
updateServerById,
|
updateServerById,
|
||||||
updateServerTraefik,
|
updateServerTraefik,
|
||||||
@@ -48,9 +51,6 @@ import {
|
|||||||
writeConfig,
|
writeConfig,
|
||||||
writeMainConfig,
|
writeMainConfig,
|
||||||
writeTraefikConfigInPath,
|
writeTraefikConfigInPath,
|
||||||
startLogCleanup,
|
|
||||||
stopLogCleanup,
|
|
||||||
getLogCleanupStatus,
|
|
||||||
} from "@dokploy/server";
|
} from "@dokploy/server";
|
||||||
import { checkGPUStatus, setupGPUSupport } from "@dokploy/server";
|
import { checkGPUStatus, setupGPUSupport } from "@dokploy/server";
|
||||||
import { generateOpenApiDocument } from "@dokploy/trpc-openapi";
|
import { generateOpenApiDocument } from "@dokploy/trpc-openapi";
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import {
|
import {
|
||||||
IS_CLOUD,
|
IS_CLOUD,
|
||||||
|
createApiKey,
|
||||||
findOrganizationById,
|
findOrganizationById,
|
||||||
findUserById,
|
findUserById,
|
||||||
getUserByToken,
|
getUserByToken,
|
||||||
removeUserById,
|
removeUserById,
|
||||||
updateUser,
|
updateUser,
|
||||||
createApiKey,
|
|
||||||
} from "@dokploy/server";
|
} from "@dokploy/server";
|
||||||
import { db } from "@dokploy/server/db";
|
import { db } from "@dokploy/server/db";
|
||||||
import {
|
import {
|
||||||
@@ -13,12 +13,12 @@ import {
|
|||||||
apiAssignPermissions,
|
apiAssignPermissions,
|
||||||
apiFindOneToken,
|
apiFindOneToken,
|
||||||
apiUpdateUser,
|
apiUpdateUser,
|
||||||
|
apikey,
|
||||||
invitation,
|
invitation,
|
||||||
member,
|
member,
|
||||||
apikey,
|
|
||||||
} from "@dokploy/server/db/schema";
|
} from "@dokploy/server/db/schema";
|
||||||
import * as bcrypt from "bcrypt";
|
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
|
import * as bcrypt from "bcrypt";
|
||||||
import { and, asc, eq, gt } from "drizzle-orm";
|
import { and, asc, eq, gt } from "drizzle-orm";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import {
|
import {
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ import { z } from "zod";
|
|||||||
import { bitbucket } from "./bitbucket";
|
import { bitbucket } from "./bitbucket";
|
||||||
import { deployments } from "./deployment";
|
import { deployments } from "./deployment";
|
||||||
import { domains } from "./domain";
|
import { domains } from "./domain";
|
||||||
|
import { gitea } from "./gitea";
|
||||||
import { github } from "./github";
|
import { github } from "./github";
|
||||||
import { gitlab } from "./gitlab";
|
import { gitlab } from "./gitlab";
|
||||||
import { gitea } from "./gitea";
|
|
||||||
import { mounts } from "./mount";
|
import { mounts } from "./mount";
|
||||||
import { ports } from "./port";
|
import { ports } from "./port";
|
||||||
import { previewDeployments } from "./preview-deployments";
|
import { previewDeployments } from "./preview-deployments";
|
||||||
@@ -395,7 +395,9 @@ const createSchema = createInsertSchema(applications, {
|
|||||||
customGitUrl: z.string().optional(),
|
customGitUrl: z.string().optional(),
|
||||||
buildPath: z.string().optional(),
|
buildPath: z.string().optional(),
|
||||||
projectId: z.string(),
|
projectId: z.string(),
|
||||||
sourceType: z.enum(["github", "docker", "git", "gitlab", "bitbucket", "gitea", "drop"]).optional(),
|
sourceType: z
|
||||||
|
.enum(["github", "docker", "git", "gitlab", "bitbucket", "gitea", "drop"])
|
||||||
|
.optional(),
|
||||||
applicationStatus: z.enum(["idle", "running", "done", "error"]),
|
applicationStatus: z.enum(["idle", "running", "done", "error"]),
|
||||||
buildType: z.enum([
|
buildType: z.enum([
|
||||||
"dockerfile",
|
"dockerfile",
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { z } from "zod";
|
|||||||
import { bitbucket } from "./bitbucket";
|
import { bitbucket } from "./bitbucket";
|
||||||
import { deployments } from "./deployment";
|
import { deployments } from "./deployment";
|
||||||
import { domains } from "./domain";
|
import { domains } from "./domain";
|
||||||
|
import { gitea } from "./gitea";
|
||||||
import { github } from "./github";
|
import { github } from "./github";
|
||||||
import { gitlab } from "./gitlab";
|
import { gitlab } from "./gitlab";
|
||||||
import { mounts } from "./mount";
|
import { mounts } from "./mount";
|
||||||
@@ -14,7 +15,6 @@ import { server } from "./server";
|
|||||||
import { applicationStatus } from "./shared";
|
import { applicationStatus } from "./shared";
|
||||||
import { sshKeys } from "./ssh-key";
|
import { sshKeys } from "./ssh-key";
|
||||||
import { generateAppName } from "./utils";
|
import { generateAppName } from "./utils";
|
||||||
import { gitea } from "./gitea";
|
|
||||||
|
|
||||||
export const sourceTypeCompose = pgEnum("sourceTypeCompose", [
|
export const sourceTypeCompose = pgEnum("sourceTypeCompose", [
|
||||||
"git",
|
"git",
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import { nanoid } from "nanoid";
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { organization } from "./account";
|
import { organization } from "./account";
|
||||||
import { bitbucket } from "./bitbucket";
|
import { bitbucket } from "./bitbucket";
|
||||||
|
import { gitea } from "./gitea";
|
||||||
import { github } from "./github";
|
import { github } from "./github";
|
||||||
import { gitlab } from "./gitlab";
|
import { gitlab } from "./gitlab";
|
||||||
import { gitea } from "./gitea";
|
|
||||||
|
|
||||||
export const gitProviderType = pgEnum("gitProviderType", [
|
export const gitProviderType = pgEnum("gitProviderType", [
|
||||||
"github",
|
"github",
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export const gitea = pgTable("gitea", {
|
|||||||
accessToken: text("access_token"),
|
accessToken: text("access_token"),
|
||||||
refreshToken: text("refresh_token"),
|
refreshToken: text("refresh_token"),
|
||||||
expiresAt: integer("expires_at"),
|
expiresAt: integer("expires_at"),
|
||||||
scopes: text("scopes").default('repo,repo:status,read:user,read:org'),
|
scopes: text("scopes").default("repo,repo:status,read:user,read:org"),
|
||||||
lastAuthenticatedAt: integer("last_authenticated_at"),
|
lastAuthenticatedAt: integer("last_authenticated_at"),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import {
|
|||||||
import { createInsertSchema } from "drizzle-zod";
|
import { createInsertSchema } from "drizzle-zod";
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { account, organization, apikey } from "./account";
|
import { account, apikey, organization } from "./account";
|
||||||
import { projects } from "./project";
|
import { projects } from "./project";
|
||||||
import { certificateType } from "./shared";
|
import { certificateType } from "./shared";
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ 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 { organization, twoFactor, apiKey } 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 { db } from "../db";
|
import { db } from "../db";
|
||||||
import * as schema from "../db/schema";
|
import * as schema from "../db/schema";
|
||||||
import { sendEmail } from "../verification/send-verification-email";
|
import { sendEmail } from "../verification/send-verification-email";
|
||||||
import { IS_CLOUD } from "../constants";
|
|
||||||
|
|
||||||
const { handler, api } = betterAuth({
|
const { handler, api } = betterAuth({
|
||||||
database: drizzleAdapter(db, {
|
database: drizzleAdapter(db, {
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import { generateObject } from "ai";
|
|||||||
import { desc, eq } from "drizzle-orm";
|
import { desc, eq } from "drizzle-orm";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { IS_CLOUD } from "../constants";
|
import { IS_CLOUD } from "../constants";
|
||||||
import { findServerById } from "./server";
|
|
||||||
import { findOrganizationById } from "./admin";
|
import { findOrganizationById } from "./admin";
|
||||||
|
import { findServerById } from "./server";
|
||||||
|
|
||||||
export const getAiSettingsByOrganizationId = async (organizationId: string) => {
|
export const getAiSettingsByOrganizationId = async (organizationId: string) => {
|
||||||
const aiSettings = await db.query.ai.findMany({
|
const aiSettings = await db.query.ai.findMany({
|
||||||
|
|||||||
@@ -26,6 +26,10 @@ import {
|
|||||||
cloneGitRepository,
|
cloneGitRepository,
|
||||||
getCustomGitCloneCommand,
|
getCustomGitCloneCommand,
|
||||||
} from "@dokploy/server/utils/providers/git";
|
} from "@dokploy/server/utils/providers/git";
|
||||||
|
import {
|
||||||
|
cloneGiteaRepository,
|
||||||
|
getGiteaCloneCommand,
|
||||||
|
} from "@dokploy/server/utils/providers/gitea";
|
||||||
import {
|
import {
|
||||||
cloneGithubRepository,
|
cloneGithubRepository,
|
||||||
getGithubCloneCommand,
|
getGithubCloneCommand,
|
||||||
@@ -34,10 +38,6 @@ import {
|
|||||||
cloneGitlabRepository,
|
cloneGitlabRepository,
|
||||||
getGitlabCloneCommand,
|
getGitlabCloneCommand,
|
||||||
} from "@dokploy/server/utils/providers/gitlab";
|
} from "@dokploy/server/utils/providers/gitlab";
|
||||||
import {
|
|
||||||
cloneGiteaRepository,
|
|
||||||
getGiteaCloneCommand,
|
|
||||||
} from "@dokploy/server/utils/providers/gitea";
|
|
||||||
import { createTraefikConfig } from "@dokploy/server/utils/traefik/application";
|
import { createTraefikConfig } from "@dokploy/server/utils/traefik/application";
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
@@ -318,10 +318,7 @@ export const deployRemoteApplication = async ({
|
|||||||
deployment.logPath,
|
deployment.logPath,
|
||||||
);
|
);
|
||||||
} else if (application.sourceType === "gitea") {
|
} else if (application.sourceType === "gitea") {
|
||||||
command += await getGiteaCloneCommand(
|
command += await getGiteaCloneCommand(application, deployment.logPath);
|
||||||
application,
|
|
||||||
deployment.logPath,
|
|
||||||
);
|
|
||||||
} else if (application.sourceType === "git") {
|
} else if (application.sourceType === "git") {
|
||||||
command += await getCustomGitCloneCommand(
|
command += await getCustomGitCloneCommand(
|
||||||
application,
|
application,
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ import {
|
|||||||
cloneGitRepository,
|
cloneGitRepository,
|
||||||
getCustomGitCloneCommand,
|
getCustomGitCloneCommand,
|
||||||
} from "@dokploy/server/utils/providers/git";
|
} from "@dokploy/server/utils/providers/git";
|
||||||
|
import {
|
||||||
|
cloneGiteaRepository,
|
||||||
|
getGiteaCloneCommand,
|
||||||
|
} from "@dokploy/server/utils/providers/gitea";
|
||||||
import {
|
import {
|
||||||
cloneGithubRepository,
|
cloneGithubRepository,
|
||||||
getGithubCloneCommand,
|
getGithubCloneCommand,
|
||||||
@@ -37,10 +41,6 @@ import {
|
|||||||
cloneGitlabRepository,
|
cloneGitlabRepository,
|
||||||
getGitlabCloneCommand,
|
getGitlabCloneCommand,
|
||||||
} from "@dokploy/server/utils/providers/gitlab";
|
} from "@dokploy/server/utils/providers/gitlab";
|
||||||
import {
|
|
||||||
cloneGiteaRepository,
|
|
||||||
getGiteaCloneCommand,
|
|
||||||
} from "@dokploy/server/utils/providers/gitea";
|
|
||||||
import {
|
import {
|
||||||
createComposeFile,
|
createComposeFile,
|
||||||
getCreateComposeFileCommand,
|
getCreateComposeFileCommand,
|
||||||
@@ -362,7 +362,7 @@ export const deployRemoteCompose = async ({
|
|||||||
command += await getGiteaCloneCommand(
|
command += await getGiteaCloneCommand(
|
||||||
compose,
|
compose,
|
||||||
deployment.logPath,
|
deployment.logPath,
|
||||||
true
|
true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ export const createGitea = async (
|
|||||||
|
|
||||||
export const findGiteaById = async (giteaId: string) => {
|
export const findGiteaById = async (giteaId: string) => {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
const giteaProviderResult = await db.query.gitea.findFirst({
|
const giteaProviderResult = await db.query.gitea.findFirst({
|
||||||
where: eq(gitea.giteaId, giteaId),
|
where: eq(gitea.giteaId, giteaId),
|
||||||
with: {
|
with: {
|
||||||
@@ -54,7 +53,7 @@ export const findGiteaById = async (giteaId: string) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!giteaProviderResult) {
|
if (!giteaProviderResult) {
|
||||||
console.error('No Gitea Provider found:', { giteaId });
|
console.error("No Gitea Provider found:", { giteaId });
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "NOT_FOUND",
|
code: "NOT_FOUND",
|
||||||
message: "Gitea Provider not found",
|
message: "Gitea Provider not found",
|
||||||
@@ -63,22 +62,19 @@ export const findGiteaById = async (giteaId: string) => {
|
|||||||
|
|
||||||
return giteaProviderResult;
|
return giteaProviderResult;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error finding Gitea Provider:', error);
|
console.error("Error finding Gitea Provider:", error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const updateGitea = async (
|
export const updateGitea = async (giteaId: string, input: Partial<Gitea>) => {
|
||||||
giteaId: string,
|
console.log("Updating Gitea Provider:", {
|
||||||
input: Partial<Gitea>,
|
|
||||||
) => {
|
|
||||||
console.log('Updating Gitea Provider:', {
|
|
||||||
giteaId,
|
giteaId,
|
||||||
updateData: {
|
updateData: {
|
||||||
accessTokenPresent: !!input.accessToken,
|
accessTokenPresent: !!input.accessToken,
|
||||||
refreshTokenPresent: !!input.refreshToken,
|
refreshTokenPresent: !!input.refreshToken,
|
||||||
expiresAt: input.expiresAt,
|
expiresAt: input.expiresAt,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -92,13 +88,13 @@ export const updateGitea = async (
|
|||||||
const result = updateResult[0] as Gitea | undefined;
|
const result = updateResult[0] as Gitea | undefined;
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
console.error('No rows were updated', { giteaId, input });
|
console.error("No rows were updated", { giteaId, input });
|
||||||
throw new Error(`Failed to update Gitea provider with ID ${giteaId}`);
|
throw new Error(`Failed to update Gitea provider with ID ${giteaId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error updating Gitea provider:', error);
|
console.error("Error updating Gitea provider:", error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -6,10 +6,10 @@ import {
|
|||||||
} from "@dokploy/server/services/deployment";
|
} from "@dokploy/server/services/deployment";
|
||||||
import { findServerById } from "@dokploy/server/services/server";
|
import { findServerById } from "@dokploy/server/services/server";
|
||||||
import {
|
import {
|
||||||
|
TRAEFIK_HTTP3_PORT,
|
||||||
TRAEFIK_PORT,
|
TRAEFIK_PORT,
|
||||||
TRAEFIK_SSL_PORT,
|
TRAEFIK_SSL_PORT,
|
||||||
TRAEFIK_VERSION,
|
TRAEFIK_VERSION,
|
||||||
TRAEFIK_HTTP3_PORT,
|
|
||||||
getDefaultMiddlewares,
|
getDefaultMiddlewares,
|
||||||
getDefaultServerTraefikConfig,
|
getDefaultServerTraefikConfig,
|
||||||
} from "@dokploy/server/setup/traefik-setup";
|
} from "@dokploy/server/setup/traefik-setup";
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { paths } from "@dokploy/server/constants";
|
import { paths } from "@dokploy/server/constants";
|
||||||
import { execAsync } from "../process/execAsync";
|
|
||||||
import { findAdmin } from "@dokploy/server/services/admin";
|
import { findAdmin } from "@dokploy/server/services/admin";
|
||||||
import { updateUser } from "@dokploy/server/services/user";
|
import { updateUser } from "@dokploy/server/services/user";
|
||||||
import { scheduleJob, scheduledJobs } from "node-schedule";
|
import { scheduleJob, scheduledJobs } from "node-schedule";
|
||||||
|
import { execAsync } from "../process/execAsync";
|
||||||
|
|
||||||
const LOG_CLEANUP_JOB_NAME = "access-log-cleanup";
|
const LOG_CLEANUP_JOB_NAME = "access-log-cleanup";
|
||||||
|
|
||||||
|
|||||||
@@ -2,19 +2,19 @@ import path from "node:path";
|
|||||||
import { getAllServers } from "@dokploy/server/services/server";
|
import { getAllServers } from "@dokploy/server/services/server";
|
||||||
import { scheduleJob } from "node-schedule";
|
import { scheduleJob } from "node-schedule";
|
||||||
import { db } from "../../db/index";
|
import { db } from "../../db/index";
|
||||||
|
import { findAdmin } from "../../services/admin";
|
||||||
import {
|
import {
|
||||||
cleanUpDockerBuilder,
|
cleanUpDockerBuilder,
|
||||||
cleanUpSystemPrune,
|
cleanUpSystemPrune,
|
||||||
cleanUpUnusedImages,
|
cleanUpUnusedImages,
|
||||||
} from "../docker/utils";
|
} from "../docker/utils";
|
||||||
import { sendDockerCleanupNotifications } from "../notifications/docker-cleanup";
|
import { sendDockerCleanupNotifications } from "../notifications/docker-cleanup";
|
||||||
|
import { execAsync, execAsyncRemote } from "../process/execAsync";
|
||||||
import { runMariadbBackup } from "./mariadb";
|
import { runMariadbBackup } from "./mariadb";
|
||||||
import { runMongoBackup } from "./mongo";
|
import { runMongoBackup } from "./mongo";
|
||||||
import { runMySqlBackup } from "./mysql";
|
import { runMySqlBackup } from "./mysql";
|
||||||
import { runPostgresBackup } from "./postgres";
|
import { runPostgresBackup } from "./postgres";
|
||||||
import { findAdmin } from "../../services/admin";
|
|
||||||
import { getS3Credentials } from "./utils";
|
import { getS3Credentials } from "./utils";
|
||||||
import { execAsync, execAsyncRemote } from "../process/execAsync";
|
|
||||||
|
|
||||||
import type { BackupSchedule } from "@dokploy/server/services/backup";
|
import type { BackupSchedule } from "@dokploy/server/services/backup";
|
||||||
import { startLogCleanup } from "../access-log/handler";
|
import { startLogCleanup } from "../access-log/handler";
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import type { BackupSchedule } from "@dokploy/server/services/backup";
|
import type { BackupSchedule } from "@dokploy/server/services/backup";
|
||||||
import type { Destination } from "@dokploy/server/services/destination";
|
import type { Destination } from "@dokploy/server/services/destination";
|
||||||
import { scheduleJob, scheduledJobs } from "node-schedule";
|
import { scheduleJob, scheduledJobs } from "node-schedule";
|
||||||
|
import { keepLatestNBackups } from ".";
|
||||||
import { runMariadbBackup } from "./mariadb";
|
import { runMariadbBackup } from "./mariadb";
|
||||||
import { runMongoBackup } from "./mongo";
|
import { runMongoBackup } from "./mongo";
|
||||||
import { runMySqlBackup } from "./mysql";
|
import { runMySqlBackup } from "./mysql";
|
||||||
import { runPostgresBackup } from "./postgres";
|
import { runPostgresBackup } from "./postgres";
|
||||||
import { keepLatestNBackups } from ".";
|
|
||||||
|
|
||||||
export const scheduleBackup = (backup: BackupSchedule) => {
|
export const scheduleBackup = (backup: BackupSchedule) => {
|
||||||
const { schedule, backupId, databaseType, postgres, mysql, mongo, mariadb } =
|
const { schedule, backupId, databaseType, postgres, mysql, mongo, mariadb } =
|
||||||
|
|||||||
@@ -112,8 +112,10 @@ export const getBuildCommand = (
|
|||||||
|
|
||||||
export const mechanizeDockerContainer = async (
|
export const mechanizeDockerContainer = async (
|
||||||
application: ApplicationNested,
|
application: ApplicationNested,
|
||||||
) => {
|
) => {
|
||||||
console.log(`Starting to mechanize Docker container for ${application.appName}`);
|
console.log(
|
||||||
|
`Starting to mechanize Docker container for ${application.appName}`,
|
||||||
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
appName,
|
appName,
|
||||||
@@ -210,7 +212,8 @@ export const mechanizeDockerContainer = async (
|
|||||||
});
|
});
|
||||||
console.log(`Service updated successfully: ${appName}`);
|
console.log(`Service updated successfully: ${appName}`);
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
const errorMessage =
|
||||||
|
error instanceof Error ? error.message : "Unknown error";
|
||||||
console.log(`Service not found or error: ${errorMessage}`);
|
console.log(`Service not found or error: ${errorMessage}`);
|
||||||
console.log(`Creating new service: ${appName}`);
|
console.log(`Creating new service: ${appName}`);
|
||||||
|
|
||||||
@@ -218,9 +221,8 @@ export const mechanizeDockerContainer = async (
|
|||||||
await docker.createService(settings);
|
await docker.createService(settings);
|
||||||
console.log(`Service created successfully: ${appName}`);
|
console.log(`Service created successfully: ${appName}`);
|
||||||
} catch (createError: unknown) {
|
} catch (createError: unknown) {
|
||||||
const createErrorMessage = createError instanceof Error
|
const createErrorMessage =
|
||||||
? createError.message
|
createError instanceof Error ? createError.message : "Unknown error";
|
||||||
: 'Unknown error';
|
|
||||||
console.error(`Failed to create service: ${createErrorMessage}`);
|
console.error(`Failed to create service: ${createErrorMessage}`);
|
||||||
throw createError;
|
throw createError;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,9 +90,10 @@ export const buildNixpacks = async (
|
|||||||
await spawnAsync("docker", ["rm", buildContainerId], writeToStream);
|
await spawnAsync("docker", ["rm", buildContainerId], writeToStream);
|
||||||
} catch (rmError) {
|
} catch (rmError) {
|
||||||
// Ignore errors from container removal
|
// Ignore errors from container removal
|
||||||
const errorMessage = rmError instanceof Error
|
const errorMessage =
|
||||||
|
rmError instanceof Error
|
||||||
? rmError.message
|
? rmError.message
|
||||||
: 'Unknown container cleanup error';
|
: "Unknown container cleanup error";
|
||||||
|
|
||||||
// Just log it but don't let it cause another error
|
// Just log it but don't let it cause another error
|
||||||
writeToStream(`Container cleanup attempt: ${errorMessage}\n`);
|
writeToStream(`Container cleanup attempt: ${errorMessage}\n`);
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
|
import { createHash } from "node:crypto";
|
||||||
import type { WriteStream } from "node:fs";
|
import type { WriteStream } from "node:fs";
|
||||||
|
import { nanoid } from "nanoid";
|
||||||
import type { ApplicationNested } from ".";
|
import type { ApplicationNested } from ".";
|
||||||
import { prepareEnvironmentVariables } from "../docker/utils";
|
import { prepareEnvironmentVariables } from "../docker/utils";
|
||||||
import { getBuildAppDirectory } from "../filesystem/directory";
|
import { getBuildAppDirectory } from "../filesystem/directory";
|
||||||
import { spawnAsync } from "../process/spawnAsync";
|
|
||||||
import { execAsync } from "../process/execAsync";
|
import { execAsync } from "../process/execAsync";
|
||||||
import { nanoid } from "nanoid";
|
import { spawnAsync } from "../process/spawnAsync";
|
||||||
import { createHash } from "node:crypto";
|
|
||||||
|
|
||||||
const calculateSecretsHash = (envVariables: string[]): string => {
|
const calculateSecretsHash = (envVariables: string[]): string => {
|
||||||
const hash = createHash("sha256");
|
const hash = createHash("sha256");
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
import { deployPostgres } from "@dokploy/server/services/postgres";
|
|
||||||
import { execAsyncRemote } from "../process/execAsync";
|
|
||||||
import { execAsync } from "../process/execAsync";
|
|
||||||
import { deployMySql } from "@dokploy/server/services/mysql";
|
|
||||||
import { deployMariadb } from "@dokploy/server/services/mariadb";
|
|
||||||
import { deployMongo } from "@dokploy/server/services/mongo";
|
|
||||||
import { deployRedis } from "@dokploy/server/services/redis";
|
|
||||||
import { removeService } from "../docker/utils";
|
|
||||||
import { db } from "@dokploy/server/db";
|
import { db } from "@dokploy/server/db";
|
||||||
import {
|
import {
|
||||||
postgres,
|
|
||||||
mysql,
|
|
||||||
mariadb,
|
mariadb,
|
||||||
mongo,
|
mongo,
|
||||||
|
mysql,
|
||||||
|
postgres,
|
||||||
redis,
|
redis,
|
||||||
} from "@dokploy/server/db/schema";
|
} from "@dokploy/server/db/schema";
|
||||||
|
import { deployMariadb } from "@dokploy/server/services/mariadb";
|
||||||
|
import { deployMongo } from "@dokploy/server/services/mongo";
|
||||||
|
import { deployMySql } from "@dokploy/server/services/mysql";
|
||||||
|
import { deployPostgres } from "@dokploy/server/services/postgres";
|
||||||
|
import { deployRedis } from "@dokploy/server/services/redis";
|
||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
|
import { removeService } from "../docker/utils";
|
||||||
|
import { execAsyncRemote } from "../process/execAsync";
|
||||||
|
import { execAsync } from "../process/execAsync";
|
||||||
|
|
||||||
type DatabaseType = "postgres" | "mysql" | "mariadb" | "mongo" | "redis";
|
type DatabaseType = "postgres" | "mysql" | "mariadb" | "mongo" | "redis";
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
cloneGitRawRepository,
|
cloneGitRawRepository,
|
||||||
cloneRawGitRepositoryRemote,
|
cloneRawGitRepositoryRemote,
|
||||||
} from "../providers/git";
|
} from "../providers/git";
|
||||||
|
import { cloneRawGiteaRepository } from "../providers/gitea";
|
||||||
import {
|
import {
|
||||||
cloneRawGithubRepository,
|
cloneRawGithubRepository,
|
||||||
cloneRawGithubRepositoryRemote,
|
cloneRawGithubRepositoryRemote,
|
||||||
@@ -22,10 +23,6 @@ import {
|
|||||||
cloneRawGitlabRepository,
|
cloneRawGitlabRepository,
|
||||||
cloneRawGitlabRepositoryRemote,
|
cloneRawGitlabRepositoryRemote,
|
||||||
} from "../providers/gitlab";
|
} from "../providers/gitlab";
|
||||||
import {
|
|
||||||
cloneRawGiteaRepository,
|
|
||||||
cloneRawGiteaRepositoryRemote,
|
|
||||||
} from "../providers/gitea";
|
|
||||||
import {
|
import {
|
||||||
createComposeFileRaw,
|
createComposeFileRaw,
|
||||||
createComposeFileRawRemote,
|
createComposeFileRawRemote,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { createWriteStream } from "node:fs";
|
import { createWriteStream } from "node:fs";
|
||||||
|
import fs from "node:fs/promises";
|
||||||
import { join } from "node:path";
|
import { join } from "node:path";
|
||||||
import fs from "fs/promises";
|
|
||||||
import { paths } from "@dokploy/server/constants";
|
import { paths } from "@dokploy/server/constants";
|
||||||
import { findGiteaById, updateGitea } from "@dokploy/server/services/gitea";
|
import { findGiteaById, updateGitea } from "@dokploy/server/services/gitea";
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
@@ -13,14 +13,16 @@ import { spawnAsync } from "../process/spawnAsync";
|
|||||||
*/
|
*/
|
||||||
export const fetchGiteaBranches = async (
|
export const fetchGiteaBranches = async (
|
||||||
giteaId: string,
|
giteaId: string,
|
||||||
repoFullName: string
|
repoFullName: string,
|
||||||
) => {
|
) => {
|
||||||
// Ensure owner and repo are non-empty strings
|
// Ensure owner and repo are non-empty strings
|
||||||
const parts = repoFullName.split('/');
|
const parts = repoFullName.split("/");
|
||||||
|
|
||||||
// Validate that we have exactly two parts
|
// Validate that we have exactly two parts
|
||||||
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
||||||
throw new Error(`Invalid repository name format: ${repoFullName}. Expected format: owner/repo`);
|
throw new Error(
|
||||||
|
`Invalid repository name format: ${repoFullName}. Expected format: owner/repo`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const [owner, repo] = parts;
|
const [owner, repo] = parts;
|
||||||
@@ -30,7 +32,7 @@ export const fetchGiteaBranches = async (
|
|||||||
giteaId,
|
giteaId,
|
||||||
owner,
|
owner,
|
||||||
repo,
|
repo,
|
||||||
id: 0 // Provide a default value for optional id
|
id: 0, // Provide a default value for optional id
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -41,10 +43,11 @@ export const getErrorCloneRequirements = (entity: {
|
|||||||
giteaRepository?: string | null;
|
giteaRepository?: string | null;
|
||||||
giteaOwner?: string | null;
|
giteaOwner?: string | null;
|
||||||
giteaBranch?: string | null;
|
giteaBranch?: string | null;
|
||||||
giteaPathNamespace?: string | null
|
giteaPathNamespace?: string | null;
|
||||||
}) => {
|
}) => {
|
||||||
const reasons: string[] = [];
|
const reasons: string[] = [];
|
||||||
const { giteaBranch, giteaOwner, giteaRepository, giteaPathNamespace } = entity;
|
const { giteaBranch, giteaOwner, giteaRepository, giteaPathNamespace } =
|
||||||
|
entity;
|
||||||
|
|
||||||
if (!giteaRepository) reasons.push("1. Repository not assigned.");
|
if (!giteaRepository) reasons.push("1. Repository not assigned.");
|
||||||
if (!giteaOwner) reasons.push("2. Owner not specified.");
|
if (!giteaOwner) reasons.push("2. Owner not specified.");
|
||||||
@@ -59,46 +62,50 @@ export const getErrorCloneRequirements = (entity: {
|
|||||||
*/
|
*/
|
||||||
export const refreshGiteaToken = async (giteaProviderId: string) => {
|
export const refreshGiteaToken = async (giteaProviderId: string) => {
|
||||||
try {
|
try {
|
||||||
console.log('Attempting to refresh Gitea token:', {
|
console.log("Attempting to refresh Gitea token:", {
|
||||||
giteaProviderId,
|
giteaProviderId,
|
||||||
timestamp: new Date().toISOString()
|
timestamp: new Date().toISOString(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const giteaProvider = await findGiteaById(giteaProviderId);
|
const giteaProvider = await findGiteaById(giteaProviderId);
|
||||||
|
|
||||||
if (!giteaProvider?.clientId || !giteaProvider?.clientSecret || !giteaProvider?.refreshToken) {
|
if (
|
||||||
console.warn('Missing credentials for token refresh');
|
!giteaProvider?.clientId ||
|
||||||
|
!giteaProvider?.clientSecret ||
|
||||||
|
!giteaProvider?.refreshToken
|
||||||
|
) {
|
||||||
|
console.warn("Missing credentials for token refresh");
|
||||||
return giteaProvider?.accessToken || null;
|
return giteaProvider?.accessToken || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const tokenEndpoint = `${giteaProvider.giteaUrl}/login/oauth/access_token`;
|
const tokenEndpoint = `${giteaProvider.giteaUrl}/login/oauth/access_token`;
|
||||||
const params = new URLSearchParams({
|
const params = new URLSearchParams({
|
||||||
grant_type: 'refresh_token',
|
grant_type: "refresh_token",
|
||||||
refresh_token: giteaProvider.refreshToken,
|
refresh_token: giteaProvider.refreshToken,
|
||||||
client_id: giteaProvider.clientId,
|
client_id: giteaProvider.clientId,
|
||||||
client_secret: giteaProvider.clientSecret,
|
client_secret: giteaProvider.clientSecret,
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('Token Endpoint:', tokenEndpoint);
|
console.log("Token Endpoint:", tokenEndpoint);
|
||||||
console.log('Request Parameters:', params.toString());
|
console.log("Request Parameters:", params.toString());
|
||||||
|
|
||||||
const response = await fetch(tokenEndpoint, {
|
const response = await fetch(tokenEndpoint, {
|
||||||
method: 'POST',
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/x-www-form-urlencoded',
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
'Accept': 'application/json'
|
Accept: "application/json",
|
||||||
},
|
},
|
||||||
body: params.toString(),
|
body: params.toString(),
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('Token Refresh Response:', {
|
console.log("Token Refresh Response:", {
|
||||||
status: response.status,
|
status: response.status,
|
||||||
statusText: response.statusText
|
statusText: response.statusText,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const errorText = await response.text();
|
const errorText = await response.text();
|
||||||
console.error('Token Refresh Failed:', errorText);
|
console.error("Token Refresh Failed:", errorText);
|
||||||
return giteaProvider?.accessToken || null;
|
return giteaProvider?.accessToken || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,11 +113,11 @@ export const refreshGiteaToken = async (giteaProviderId: string) => {
|
|||||||
const { access_token, refresh_token, expires_in } = data;
|
const { access_token, refresh_token, expires_in } = data;
|
||||||
|
|
||||||
if (!access_token) {
|
if (!access_token) {
|
||||||
console.error('Missing access token in refresh response');
|
console.error("Missing access token in refresh response");
|
||||||
return giteaProvider?.accessToken || null;
|
return giteaProvider?.accessToken || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const expiresAt = Date.now() + ((expires_in || 3600) * 1000);
|
const expiresAt = Date.now() + (expires_in || 3600) * 1000;
|
||||||
const expiresAtSeconds = Math.floor(expiresAt / 1000);
|
const expiresAtSeconds = Math.floor(expiresAt / 1000);
|
||||||
|
|
||||||
await updateGitea(giteaProviderId, {
|
await updateGitea(giteaProviderId, {
|
||||||
@@ -119,10 +126,10 @@ export const refreshGiteaToken = async (giteaProviderId: string) => {
|
|||||||
expiresAt: expiresAtSeconds,
|
expiresAt: expiresAtSeconds,
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('Gitea token refreshed successfully.');
|
console.log("Gitea token refreshed successfully.");
|
||||||
return access_token;
|
return access_token;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Token Refresh Error:', error);
|
console.error("Token Refresh Error:", error);
|
||||||
// Return the existing token if refresh fails
|
// Return the existing token if refresh fails
|
||||||
const giteaProvider = await findGiteaById(giteaProviderId);
|
const giteaProvider = await findGiteaById(giteaProviderId);
|
||||||
return giteaProvider?.accessToken || null;
|
return giteaProvider?.accessToken || null;
|
||||||
@@ -132,8 +139,19 @@ export const refreshGiteaToken = async (giteaProviderId: string) => {
|
|||||||
/**
|
/**
|
||||||
* Generate a secure Git clone command with proper validation
|
* Generate a secure Git clone command with proper validation
|
||||||
*/
|
*/
|
||||||
export const getGiteaCloneCommand = async (entity: any, logPath: string, isCompose = false) => {
|
export const getGiteaCloneCommand = async (
|
||||||
const { appName, giteaBranch, giteaId, giteaOwner, giteaRepository, serverId } = entity;
|
entity: any,
|
||||||
|
logPath: string,
|
||||||
|
isCompose = false,
|
||||||
|
) => {
|
||||||
|
const {
|
||||||
|
appName,
|
||||||
|
giteaBranch,
|
||||||
|
giteaId,
|
||||||
|
giteaOwner,
|
||||||
|
giteaRepository,
|
||||||
|
serverId,
|
||||||
|
} = entity;
|
||||||
|
|
||||||
if (!serverId) {
|
if (!serverId) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
@@ -155,7 +173,7 @@ export const getGiteaCloneCommand = async (entity: any, logPath: string, isCompo
|
|||||||
const outputPath = join(basePath, appName, "code");
|
const outputPath = join(basePath, appName, "code");
|
||||||
|
|
||||||
const giteaProvider = await findGiteaById(giteaId);
|
const giteaProvider = await findGiteaById(giteaId);
|
||||||
const baseUrl = giteaProvider.giteaUrl.replace(/^https?:\/\//, '');
|
const baseUrl = giteaProvider.giteaUrl.replace(/^https?:\/\//, "");
|
||||||
const repoClone = `${giteaOwner}/${giteaRepository}.git`;
|
const repoClone = `${giteaOwner}/${giteaRepository}.git`;
|
||||||
const cloneUrl = `https://oauth2:${giteaProvider.accessToken}@${baseUrl}/${repoClone}`;
|
const cloneUrl = `https://oauth2:${giteaProvider.accessToken}@${baseUrl}/${repoClone}`;
|
||||||
|
|
||||||
@@ -194,13 +212,15 @@ export const getGiteaCloneCommand = async (entity: any, logPath: string, isCompo
|
|||||||
export const cloneGiteaRepository = async (
|
export const cloneGiteaRepository = async (
|
||||||
entity: any,
|
entity: any,
|
||||||
logPath?: string,
|
logPath?: string,
|
||||||
isCompose: boolean = false
|
isCompose = false,
|
||||||
) => {
|
) => {
|
||||||
// If logPath is not provided, generate a default log path
|
// If logPath is not provided, generate a default log path
|
||||||
const actualLogPath = logPath || join(
|
const actualLogPath =
|
||||||
paths()[isCompose ? 'COMPOSE_PATH' : 'APPLICATIONS_PATH'],
|
logPath ||
|
||||||
|
join(
|
||||||
|
paths()[isCompose ? "COMPOSE_PATH" : "APPLICATIONS_PATH"],
|
||||||
entity.appName,
|
entity.appName,
|
||||||
'clone.log'
|
"clone.log",
|
||||||
);
|
);
|
||||||
|
|
||||||
const writeStream = createWriteStream(actualLogPath, { flags: "a" });
|
const writeStream = createWriteStream(actualLogPath, { flags: "a" });
|
||||||
@@ -231,7 +251,7 @@ export const cloneGiteaRepository = async (
|
|||||||
const outputPath = join(basePath, appName, "code");
|
const outputPath = join(basePath, appName, "code");
|
||||||
|
|
||||||
// Log path information
|
// Log path information
|
||||||
writeStream.write(`\nPath Information:\n`);
|
writeStream.write("\nPath Information:\n");
|
||||||
writeStream.write(`Base Path: ${basePath}\n`);
|
writeStream.write(`Base Path: ${basePath}\n`);
|
||||||
writeStream.write(`Output Path: ${outputPath}\n`);
|
writeStream.write(`Output Path: ${outputPath}\n`);
|
||||||
|
|
||||||
@@ -241,19 +261,24 @@ export const cloneGiteaRepository = async (
|
|||||||
// Additional step - verify directory exists and is empty
|
// Additional step - verify directory exists and is empty
|
||||||
try {
|
try {
|
||||||
const filesCheck = await fs.readdir(outputPath);
|
const filesCheck = await fs.readdir(outputPath);
|
||||||
writeStream.write(`Directory after cleanup - files: ${filesCheck.length}\n`);
|
writeStream.write(
|
||||||
|
`Directory after cleanup - files: ${filesCheck.length}\n`,
|
||||||
|
);
|
||||||
|
|
||||||
if (filesCheck.length > 0) {
|
if (filesCheck.length > 0) {
|
||||||
writeStream.write(`WARNING: Directory not empty after cleanup!\n`);
|
writeStream.write("WARNING: Directory not empty after cleanup!\n");
|
||||||
|
|
||||||
// Force remove with shell command if recreateDirectory didn't work
|
// Force remove with shell command if recreateDirectory didn't work
|
||||||
if (entity.serverId) {
|
if (entity.serverId) {
|
||||||
writeStream.write(`Attempting forceful cleanup via shell command\n`);
|
writeStream.write("Attempting forceful cleanup via shell command\n");
|
||||||
await execAsyncRemote(entity.serverId, `rm -rf "${outputPath}" && mkdir -p "${outputPath}"`,
|
await execAsyncRemote(
|
||||||
data => writeStream.write(`Cleanup output: ${data}\n`));
|
entity.serverId,
|
||||||
|
`rm -rf "${outputPath}" && mkdir -p "${outputPath}"`,
|
||||||
|
(data) => writeStream.write(`Cleanup output: ${data}\n`),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
// Fallback to direct fs operations if serverId not available
|
// Fallback to direct fs operations if serverId not available
|
||||||
writeStream.write(`Attempting direct fs removal\n`);
|
writeStream.write("Attempting direct fs removal\n");
|
||||||
await fs.rm(outputPath, { recursive: true, force: true });
|
await fs.rm(outputPath, { recursive: true, force: true });
|
||||||
await fs.mkdir(outputPath, { recursive: true });
|
await fs.mkdir(outputPath, { recursive: true });
|
||||||
}
|
}
|
||||||
@@ -264,11 +289,13 @@ export const cloneGiteaRepository = async (
|
|||||||
}
|
}
|
||||||
|
|
||||||
const repoClone = `${giteaOwner}/${giteaRepository}.git`;
|
const repoClone = `${giteaOwner}/${giteaRepository}.git`;
|
||||||
const baseUrl = giteaProvider.giteaUrl.replace(/^https?:\/\//, '');
|
const baseUrl = giteaProvider.giteaUrl.replace(/^https?:\/\//, "");
|
||||||
const cloneUrl = `https://oauth2:${giteaProvider.accessToken}@${baseUrl}/${repoClone}`;
|
const cloneUrl = `https://oauth2:${giteaProvider.accessToken}@${baseUrl}/${repoClone}`;
|
||||||
|
|
||||||
writeStream.write(`\nCloning Repo ${repoClone} to ${outputPath}...\n`);
|
writeStream.write(`\nCloning Repo ${repoClone} to ${outputPath}...\n`);
|
||||||
writeStream.write(`Clone URL (masked): https://oauth2:***@${baseUrl}/${repoClone}\n`);
|
writeStream.write(
|
||||||
|
`Clone URL (masked): https://oauth2:***@${baseUrl}/${repoClone}\n`,
|
||||||
|
);
|
||||||
|
|
||||||
// First try standard git clone
|
// First try standard git clone
|
||||||
try {
|
try {
|
||||||
@@ -283,38 +310,43 @@ export const cloneGiteaRepository = async (
|
|||||||
"--recurse-submodules",
|
"--recurse-submodules",
|
||||||
cloneUrl,
|
cloneUrl,
|
||||||
outputPath,
|
outputPath,
|
||||||
"--progress"
|
"--progress",
|
||||||
],
|
],
|
||||||
(data) => {
|
(data) => {
|
||||||
if (writeStream.writable) {
|
if (writeStream.writable) {
|
||||||
writeStream.write(data);
|
writeStream.write(data);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
writeStream.write(`\nStandard git clone succeeded\n`);
|
writeStream.write("\nStandard git clone succeeded\n");
|
||||||
} catch (cloneError) {
|
} catch (cloneError) {
|
||||||
writeStream.write(`\nStandard git clone failed: ${cloneError}\n`);
|
writeStream.write(`\nStandard git clone failed: ${cloneError}\n`);
|
||||||
writeStream.write(`Falling back to git init + fetch approach...\n`);
|
writeStream.write("Falling back to git init + fetch approach...\n");
|
||||||
|
|
||||||
// Retry cleanup one more time
|
// Retry cleanup one more time
|
||||||
if (entity.serverId) {
|
if (entity.serverId) {
|
||||||
await execAsyncRemote(entity.serverId, `rm -rf "${outputPath}" && mkdir -p "${outputPath}"`,
|
await execAsyncRemote(
|
||||||
data => writeStream.write(`Cleanup retry: ${data}\n`));
|
entity.serverId,
|
||||||
|
`rm -rf "${outputPath}" && mkdir -p "${outputPath}"`,
|
||||||
|
(data) => writeStream.write(`Cleanup retry: ${data}\n`),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
await fs.rm(outputPath, { recursive: true, force: true });
|
await fs.rm(outputPath, { recursive: true, force: true });
|
||||||
await fs.mkdir(outputPath, { recursive: true });
|
await fs.mkdir(outputPath, { recursive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize git repo
|
// Initialize git repo
|
||||||
writeStream.write(`Initializing git repository...\n`);
|
writeStream.write("Initializing git repository...\n");
|
||||||
await spawnAsync("git", ["init", outputPath], data => writeStream.write(data));
|
await spawnAsync("git", ["init", outputPath], (data) =>
|
||||||
|
writeStream.write(data),
|
||||||
|
);
|
||||||
|
|
||||||
// Set remote origin
|
// Set remote origin
|
||||||
writeStream.write(`Setting remote origin...\n`);
|
writeStream.write("Setting remote origin...\n");
|
||||||
await spawnAsync(
|
await spawnAsync(
|
||||||
"git",
|
"git",
|
||||||
["-C", outputPath, "remote", "add", "origin", cloneUrl],
|
["-C", outputPath, "remote", "add", "origin", cloneUrl],
|
||||||
data => writeStream.write(data)
|
(data) => writeStream.write(data),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Fetch branch
|
// Fetch branch
|
||||||
@@ -322,7 +354,7 @@ export const cloneGiteaRepository = async (
|
|||||||
await spawnAsync(
|
await spawnAsync(
|
||||||
"git",
|
"git",
|
||||||
["-C", outputPath, "fetch", "--depth", "1", "origin", giteaBranch],
|
["-C", outputPath, "fetch", "--depth", "1", "origin", giteaBranch],
|
||||||
data => writeStream.write(data)
|
(data) => writeStream.write(data),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Checkout branch
|
// Checkout branch
|
||||||
@@ -330,18 +362,21 @@ export const cloneGiteaRepository = async (
|
|||||||
await spawnAsync(
|
await spawnAsync(
|
||||||
"git",
|
"git",
|
||||||
["-C", outputPath, "checkout", "FETCH_HEAD"],
|
["-C", outputPath, "checkout", "FETCH_HEAD"],
|
||||||
data => writeStream.write(data)
|
(data) => writeStream.write(data),
|
||||||
);
|
);
|
||||||
|
|
||||||
writeStream.write(`Git init and fetch completed successfully\n`);
|
writeStream.write("Git init and fetch completed successfully\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify clone
|
// Verify clone
|
||||||
const files = await fs.readdir(outputPath);
|
const files = await fs.readdir(outputPath);
|
||||||
writeStream.write(`\nClone Verification:\n`);
|
writeStream.write("\nClone Verification:\n");
|
||||||
writeStream.write(`Files found: ${files.length}\n`);
|
writeStream.write(`Files found: ${files.length}\n`);
|
||||||
if (files.length > 0) {
|
if (files.length > 0) {
|
||||||
files.slice(0, 10).forEach(file => writeStream.write(`- ${file}\n`));
|
// Using a for loop instead of forEach
|
||||||
|
for (let i = 0; i < Math.min(files.length, 10); i++) {
|
||||||
|
writeStream.write(`- ${files[i]}\n`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (files.length === 0) {
|
if (files.length === 0) {
|
||||||
@@ -357,7 +392,6 @@ export const cloneGiteaRepository = async (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clone a Gitea repository locally for a Compose configuration
|
* Clone a Gitea repository locally for a Compose configuration
|
||||||
* Leverages the existing comprehensive cloneGiteaRepository function
|
* Leverages the existing comprehensive cloneGiteaRepository function
|
||||||
@@ -366,8 +400,8 @@ export const cloneRawGiteaRepository = async (entity: any) => {
|
|||||||
// Merge the existing entity with compose-specific properties
|
// Merge the existing entity with compose-specific properties
|
||||||
const composeEntity = {
|
const composeEntity = {
|
||||||
...entity,
|
...entity,
|
||||||
sourceType: 'compose',
|
sourceType: "compose",
|
||||||
isCompose: true
|
isCompose: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Call cloneGiteaRepository with the modified entity
|
// Call cloneGiteaRepository with the modified entity
|
||||||
@@ -380,13 +414,17 @@ export const cloneRawGiteaRepository = async (entity: any) => {
|
|||||||
*/
|
*/
|
||||||
export const cloneRawGiteaRepositoryRemote = async (compose: any) => {
|
export const cloneRawGiteaRepositoryRemote = async (compose: any) => {
|
||||||
const { COMPOSE_PATH } = paths(true);
|
const { COMPOSE_PATH } = paths(true);
|
||||||
const logPath = join(COMPOSE_PATH, compose.appName, 'clone.log');
|
const logPath = join(COMPOSE_PATH, compose.appName, "clone.log");
|
||||||
|
|
||||||
// Reuse the existing getGiteaCloneCommand function
|
// Reuse the existing getGiteaCloneCommand function
|
||||||
const command = await getGiteaCloneCommand({
|
const command = await getGiteaCloneCommand(
|
||||||
|
{
|
||||||
...compose,
|
...compose,
|
||||||
isCompose: true
|
isCompose: true,
|
||||||
}, logPath, true);
|
},
|
||||||
|
logPath,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
if (!compose.serverId) {
|
if (!compose.serverId) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
@@ -424,7 +462,7 @@ export const testGiteaConnection = async (input: { giteaId: string }) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Gitea Provider Found:', {
|
console.log("Gitea Provider Found:", {
|
||||||
id: giteaProvider.giteaId,
|
id: giteaProvider.giteaId,
|
||||||
url: giteaProvider.giteaUrl,
|
url: giteaProvider.giteaUrl,
|
||||||
hasAccessToken: !!giteaProvider.accessToken,
|
hasAccessToken: !!giteaProvider.accessToken,
|
||||||
@@ -443,38 +481,42 @@ export const testGiteaConnection = async (input: { giteaId: string }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make API request to test connection
|
// Make API request to test connection
|
||||||
console.log('Making API request to test connection...');
|
console.log("Making API request to test connection...");
|
||||||
|
|
||||||
// Construct proper URL for the API request
|
// Construct proper URL for the API request
|
||||||
const baseUrl = provider.giteaUrl.replace(/\/+$/, ''); // Remove trailing slashes
|
const baseUrl = provider.giteaUrl.replace(/\/+$/, ""); // Remove trailing slashes
|
||||||
const url = `${baseUrl}/api/v1/user/repos`;
|
const url = `${baseUrl}/api/v1/user/repos`;
|
||||||
|
|
||||||
console.log(`Testing connection to: ${url}`);
|
console.log(`Testing connection to: ${url}`);
|
||||||
|
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
headers: {
|
headers: {
|
||||||
'Accept': 'application/json',
|
Accept: "application/json",
|
||||||
'Authorization': `token ${provider.accessToken}`
|
Authorization: `token ${provider.accessToken}`,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const errorText = await response.text();
|
const errorText = await response.text();
|
||||||
console.error('Repository API failed:', errorText);
|
console.error("Repository API failed:", errorText);
|
||||||
throw new Error(`Failed to connect to Gitea API: ${response.status} ${response.statusText}`);
|
throw new Error(
|
||||||
|
`Failed to connect to Gitea API: ${response.status} ${response.statusText}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const repos = await response.json();
|
const repos = await response.json();
|
||||||
console.log(`Successfully connected to Gitea API. Found ${repos.length} repositories.`);
|
console.log(
|
||||||
|
`Successfully connected to Gitea API. Found ${repos.length} repositories.`,
|
||||||
|
);
|
||||||
|
|
||||||
// Update lastAuthenticatedAt
|
// Update lastAuthenticatedAt
|
||||||
await updateGitea(giteaId, {
|
await updateGitea(giteaId, {
|
||||||
lastAuthenticatedAt: Math.floor(Date.now() / 1000)
|
lastAuthenticatedAt: Math.floor(Date.now() / 1000),
|
||||||
});
|
});
|
||||||
|
|
||||||
return repos.length;
|
return repos.length;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Gitea Connection Test Error:', error);
|
console.error("Gitea Connection Test Error:", error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -494,14 +536,14 @@ export const getGiteaRepositories = async (giteaId?: string) => {
|
|||||||
const giteaProvider = await findGiteaById(giteaId);
|
const giteaProvider = await findGiteaById(giteaId);
|
||||||
|
|
||||||
// Construct the URL for fetching repositories
|
// Construct the URL for fetching repositories
|
||||||
const baseUrl = giteaProvider.giteaUrl.replace(/\/+$/, '');
|
const baseUrl = giteaProvider.giteaUrl.replace(/\/+$/, "");
|
||||||
const url = `${baseUrl}/api/v1/user/repos`;
|
const url = `${baseUrl}/api/v1/user/repos`;
|
||||||
|
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
headers: {
|
headers: {
|
||||||
'Accept': 'application/json',
|
Accept: "application/json",
|
||||||
'Authorization': `token ${giteaProvider.accessToken}`
|
Authorization: `token ${giteaProvider.accessToken}`,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
@@ -519,8 +561,8 @@ export const getGiteaRepositories = async (giteaId?: string) => {
|
|||||||
name: repo.name,
|
name: repo.name,
|
||||||
url: repo.full_name,
|
url: repo.full_name,
|
||||||
owner: {
|
owner: {
|
||||||
username: repo.owner.login
|
username: repo.owner.login,
|
||||||
}
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return mappedRepositories;
|
return mappedRepositories;
|
||||||
@@ -543,14 +585,14 @@ export const getGiteaBranches = async (input: {
|
|||||||
const giteaProvider = await findGiteaById(input.giteaId);
|
const giteaProvider = await findGiteaById(input.giteaId);
|
||||||
|
|
||||||
// Construct the URL for fetching branches
|
// Construct the URL for fetching branches
|
||||||
const baseUrl = giteaProvider.giteaUrl.replace(/\/+$/, '');
|
const baseUrl = giteaProvider.giteaUrl.replace(/\/+$/, "");
|
||||||
const url = `${baseUrl}/api/v1/repos/${input.owner}/${input.repo}/branches`;
|
const url = `${baseUrl}/api/v1/repos/${input.owner}/${input.repo}/branches`;
|
||||||
|
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
headers: {
|
headers: {
|
||||||
'Accept': 'application/json',
|
Accept: "application/json",
|
||||||
'Authorization': `token ${giteaProvider.accessToken}`
|
Authorization: `token ${giteaProvider.accessToken}`,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
@@ -564,8 +606,8 @@ export const getGiteaBranches = async (input: {
|
|||||||
id: branch.name,
|
id: branch.name,
|
||||||
name: branch.name,
|
name: branch.name,
|
||||||
commit: {
|
commit: {
|
||||||
id: branch.commit.id
|
id: branch.commit.id,
|
||||||
}
|
},
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -578,5 +620,5 @@ export default {
|
|||||||
testGiteaConnection,
|
testGiteaConnection,
|
||||||
getGiteaRepositories,
|
getGiteaRepositories,
|
||||||
getGiteaBranches,
|
getGiteaBranches,
|
||||||
fetchGiteaBranches
|
fetchGiteaBranches,
|
||||||
};
|
};
|
||||||
4
pnpm-lock.yaml
generated
4
pnpm-lock.yaml
generated
@@ -242,7 +242,7 @@ importers:
|
|||||||
specifier: ^10.43.6
|
specifier: ^10.43.6
|
||||||
version: 10.45.2(@tanstack/react-query@4.36.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/client@10.45.2(@trpc/server@10.45.2))(@trpc/server@10.45.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
version: 10.45.2(@tanstack/react-query@4.36.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/client@10.45.2(@trpc/server@10.45.2))(@trpc/server@10.45.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
||||||
'@trpc/server':
|
'@trpc/server':
|
||||||
specifier: ^10.43.6
|
specifier: ^10.45.2
|
||||||
version: 10.45.2
|
version: 10.45.2
|
||||||
'@uiw/codemirror-theme-github':
|
'@uiw/codemirror-theme-github':
|
||||||
specifier: ^4.22.1
|
specifier: ^4.22.1
|
||||||
@@ -471,7 +471,7 @@ importers:
|
|||||||
specifier: 4.0.9
|
specifier: 4.0.9
|
||||||
version: 4.0.9
|
version: 4.0.9
|
||||||
'@types/node':
|
'@types/node':
|
||||||
specifier: ^18.17.0
|
specifier: ^18.19.42
|
||||||
version: 18.19.42
|
version: 18.19.42
|
||||||
'@types/node-os-utils':
|
'@types/node-os-utils':
|
||||||
specifier: 1.3.4
|
specifier: 1.3.4
|
||||||
|
|||||||
Reference in New Issue
Block a user