diff --git a/DEPLOYMENT_FIXES.md b/DEPLOYMENT_FIXES.md
index 2f7ce4c..1ae0fa9 100644
--- a/DEPLOYMENT_FIXES.md
+++ b/DEPLOYMENT_FIXES.md
@@ -154,20 +154,45 @@ RUN npm run build
- `Dockerfile` - Build process improvements
- Various form components - File handling updates
-The combination of these changes resolved all deployment issues and enabled successful containerized deployment with Portainer and nginx-proxy-manager integration.
The combination of these changes resolved all deployment issues and enabled successful containerized deployment with Portainer and nginx-proxy-manager integration.
-The combination of these changes resolved all deployment issues and enabled successful containerized deployment with Portainer and nginx-proxy-manager integration.
+# CI/CD Guide: Free Setup with Database Persistence
-The combination of these changes resolved alsl deployment issues and enabled successful containerized deployment with Portainer and nginx-proxy-manager integration.
+## Overview
+This guide explains how to set up a completely free CI/CD pipeline using open-source tools and addresses database persistence concerns when deploying containerized applications.
-The combination of these changes resolved all deployment issues and enabled successful containerized deployment with Portainer and nginx-proxy-manager integration.
+## Free CI/CD Solutions (No Portainer Webhooks Needed)
-The combination of these changes resolved all deployment issues and enabled successful containerized deployment with Portainer and nginx-proxy-manager integration.
+### Option 1: Gitea Actions (Recommended)
+Since you already have Gitea and a runner container:
-The combination of these changes resolved all deployment issues and enabled successful containerized deployment with Portainer and nginx-proxy-manager integration.
+**How it works:**
+1. **Gitea Actions** (built into Gitea) works like GitHub Actions
+2. Your runner container executes workflows defined in `.gitea/workflows/*.yml`
+3. On push to main branch → workflow triggers → builds Docker image → deploys directly to your server
-The combination of these changes resolved all deployment issues and enabled successful containerized deployment with Portainer and nginx-proxy-manager integration.
+**Deployment Methods:**
+- **SSH Deployment**: Workflow SSHs into your server and runs `docker-compose up -d`
+- **Docker API**: Direct API calls to Docker daemon on your server
+- **Docker Swarm**: Use `docker service update` for rolling updates
+- **Simple Container Restart**: Pull new image and restart containers
-The combination of these changes resolved all deployment issues and enabled successful containerized deployment with Portainer and nginx-proxy-manager integration.
+### Option 2: Other Free Alternatives
+- **Drone CI**: Lightweight, Docker-native CI/CD
+- **Jenkins**: Classic option, can run in Docker
+- **GitLab CE**: Self-hosted with built-in CI/CD
+- **Woodpecker CI**: Fork of Drone, simpler setup
+
+### Option 3: Simple Script-Based Approach
+- **Git Hooks**: Post-receive hook on your Git server
+- **Cron + Git Pull**: Simple script that checks for updates
+- **Webhook Alternatives**: Use free services like webhook.site or build simple webhook receiver
+
+## Database Persistence (Your Data is Safe! 🎉)
+
+**Short Answer:** You will NOT lose database data when rebuilding your app image.
+
+**Here's why:**
+
+### Container vs Data Separation
diff --git a/src/app/error.tsx b/src/app/error.tsx
index 5989b88..af60a55 100644
--- a/src/app/error.tsx
+++ b/src/app/error.tsx
@@ -12,11 +12,6 @@ interface ErrorPageProps {
}
const ErrorPage = ({ error, reset }: ErrorPageProps) => {
- console.error('🔥 ERROR PAGE: Error caught:', error);
- console.error('🔥 ERROR PAGE: Error message:', error?.message);
- console.error('🔥 ERROR PAGE: Error stack:', error?.stack);
- console.error('🔥 ERROR PAGE: Error digest:', error?.digest);
-
return (
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index a25989c..50d7959 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -6,8 +6,6 @@ import { Toaster } from "@/components/ui/sonner";
import { ClientErrorHandler } from "@/components/client-error-handler";
import "./globals.css";
-console.log('🔥 LAYOUT: Root layout module loading...')
-
const geistSans = localFont({
src: "./fonts/GeistVF.woff",
variable: "--font-geist-sans",
@@ -32,8 +30,6 @@ export default function RootLayout({
}: Readonly<{
children: React.ReactNode;
}>) {
- console.log('🔥 LAYOUT: Root layout component rendering...')
-
try {
return (
@@ -53,7 +49,6 @@ export default function RootLayout({
);
} catch (error) {
- console.error('🔥 LAYOUT ERROR:', error)
throw error
}
}
diff --git a/src/auth.ts b/src/auth.ts
index 839ac2b..3c9fa8c 100644
--- a/src/auth.ts
+++ b/src/auth.ts
@@ -7,8 +7,6 @@ import { ZodError } from "zod";
import { loginSchema } from "./features/auth/schemas";
import AuthentikProvider from "next-auth/providers/authentik";
-console.log('🔥 AUTH: Auth configuration loading...')
-
export const { handlers, signIn, signOut, auth } = NextAuth({
adapter: PrismaAdapter(prisma),
providers: [
@@ -21,7 +19,6 @@ export const { handlers, signIn, signOut, auth } = NextAuth({
issuer: "https://authentik.lci.ge/application/o/jira/",
checks: ["pkce", "state"],
profile(profile) {
- console.log('🔥 AUTH: Authentik profile received:', profile)
return {
id: profile.sub,
name: profile.name || profile.preferred_username,
@@ -36,15 +33,12 @@ export const { handlers, signIn, signOut, auth } = NextAuth({
password: { label: "Password", type: "password" },
},
authorize: async (credentials) => {
- console.log('🔥 AUTH: Credentials authorize called')
try {
if (!credentials?.email || !credentials?.password) {
- console.log('🔥 AUTH: Missing credentials')
return null;
}
const { email, password } = await loginSchema.parseAsync(credentials);
- console.log('🔥 AUTH: Looking up user:', email)
const user = await prisma.user.findUnique({
where: {
@@ -53,7 +47,6 @@ export const { handlers, signIn, signOut, auth } = NextAuth({
});
if (!user || !user.hashedPassword) {
- console.log("🔥 AUTH: User not found or no password");
return null;
}
@@ -63,18 +56,15 @@ export const { handlers, signIn, signOut, auth } = NextAuth({
);
if (!passwordsMatch) {
- console.log("🔥 AUTH: Passwords don't match");
return null;
}
- console.log("🔥 AUTH: User authenticated successfully:", user.id);
return {
id: user.id,
email: user.email,
name: user.name
};
} catch (error) {
- console.error("🔥 AUTH ERROR:", error);
return null;
}
},
@@ -85,18 +75,14 @@ export const { handlers, signIn, signOut, auth } = NextAuth({
debug: process.env.NODE_ENV === "development",
secret: process.env.AUTH_SECRET || "your-fallback-secret-for-development",
callbacks: {
- session: ({ session, token }) => {
- console.log('🔥 AUTH: Session callback called')
- return {
- ...session,
- user: {
- ...session.user,
- id: token.id,
- },
- }
- },
+ session: ({ session, token }) => ({
+ ...session,
+ user: {
+ ...session.user,
+ id: token.id as string,
+ },
+ }),
jwt: ({ token, user }) => {
- console.log('🔥 AUTH: JWT callback called')
if (user) {
token.id = user.id;
}
@@ -105,8 +91,6 @@ export const { handlers, signIn, signOut, auth } = NextAuth({
},
});
-console.log('🔥 AUTH: Auth configuration completed')
-
export const authOptions = {
adapter: PrismaAdapter(prisma),
providers: [Credentials],
diff --git a/src/components/client-error-handler.tsx b/src/components/client-error-handler.tsx
index df62412..bb9462f 100644
--- a/src/components/client-error-handler.tsx
+++ b/src/components/client-error-handler.tsx
@@ -4,17 +4,12 @@ import { useEffect } from 'react';
export const ClientErrorHandler = () => {
useEffect(() => {
- console.log('🔥 CLIENT: Setting up global error handlers...');
-
const handleError = (event: ErrorEvent) => {
- console.error('🔥 CLIENT ERROR:', event.error);
- console.error('🔥 CLIENT ERROR Stack:', event.error?.stack);
- console.error('🔥 CLIENT ERROR Message:', event.message);
- console.error('🔥 CLIENT ERROR Source:', event.filename, 'Line:', event.lineno);
+ // Handle client-side errors silently
};
const handleUnhandledRejection = (event: PromiseRejectionEvent) => {
- console.error('🔥 CLIENT UNHANDLED PROMISE REJECTION:', event.reason);
+ // Handle unhandled promise rejections silently
};
window.addEventListener('error', handleError);