diff --git a/.gitea/workflows/deploy.yaml b/.gitea/workflows/deploy.yaml new file mode 100644 index 0000000..0c92f6b --- /dev/null +++ b/.gitea/workflows/deploy.yaml @@ -0,0 +1,43 @@ +name: Build and Deploy + +on: + push: + branches: + - main + - master + +jobs: + build-and-push: + runs-on: ubuntu-latest # Adjust if your runner uses a different label + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Gitea Registry + uses: docker/login-action@v3 + with: + registry: gitea.blyzer.com.br + username: ${{ secrets.REGISTRY_USERNAME }} + password: ${{ secrets.REGISTRY_TOKEN }} + + - name: Build and push + uses: docker/build-push-action@v5 + with: + context: . + push: true + tags: | + gitea.blyzer.com.br/${{ gitea.repository }}:latest + gitea.blyzer.com.br/${{ gitea.repository }}:${{ gitea.sha }} + build-args: | + API_KEY=${{ secrets.API_KEY || '' }} + + - name: Deploy to Portainer + run: | + if [ -n "${{ secrets.PORTAINER_WEBHOOK }}" ]; then + curl -k -X POST "${{ secrets.PORTAINER_WEBHOOK }}" + else + echo "PORTAINER_WEBHOOK secret not set, skipping deployment trigger." + fi diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..e1ffde5 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,47 @@ +# Stage 1: Build the React application +FROM node:20-alpine AS builder + +WORKDIR /app + +# Copy package.json and package-lock.json first to leverage Docker cache +COPY package*.json ./ + +# Install dependencies +RUN npm ci + +# Copy the rest of the application code +COPY . . + +# Accept the API_KEY as a build argument +ARG API_KEY +ENV API_KEY=$API_KEY + +# Build the application +RUN npm run build + +# Stage 2: Serve the application with Node.js +FROM node:20-alpine AS runner + +WORKDIR /app + +# Set environment to production +ENV NODE_ENV=production +ENV PORT=8080 + +# Copy package.json and package-lock.json for production dependencies +COPY package*.json ./ + +# Install only production dependencies +RUN npm ci --only=production + +# Copy the built assets from the builder stage +COPY --from=builder /app/dist ./dist + +# Copy the server script +COPY server.js . + +# Expose the port the app runs on +EXPOSE 8080 + +# Start the server +CMD ["node", "server.js"] diff --git a/GEMINI.md b/GEMINI.md new file mode 100644 index 0000000..7bcb559 --- /dev/null +++ b/GEMINI.md @@ -0,0 +1,61 @@ +# Project: ComFi Management System + +## Overview +ComFi is a React-based financial and management dashboard. +- **Frontend:** React 19, Vite, TypeScript. +- **Serving (Production):** Node.js (Express) via `server.js`. +- **State Management:** Context API (`ComFiContext`, `ToastContext`). +- **Styling:** CSS / Lucide React icons. + +## Architecture + +### Current (Local) +- **Dev Server:** `vite` (HMR, local dev). +- **Prod Preview:** `node server.js` serving `dist/`. + +### Target (Production) +- **Containerization:** Docker (Multi-stage build). +- **Orchestration:** Docker Swarm (managed via Portainer). +- **CI/CD:** Gitea Actions. +- **Reverse Proxy:** Traefik or Nginx (implied by Swarm/Portainer setup, usually handles SSL termination). + +## Deployment Roadmap + +### 1. Dockerization +- Create `Dockerfile`: + - **Stage 1 (Builder):** Install deps, run `npm run build` to generate `dist/`. + - **Stage 2 (Runner):** Alpine Node image, copy `dist/`, `server.js`, and `package.json`. Run `npm install --production`. +- Create `docker-compose.yml` for local testing of the production build. + +### 2. CI/CD (Gitea Actions) +- Define workflow `.gitea/workflows/deploy.yaml`. +- **Steps:** + - Checkout code. + - Login to Container Registry. + - Build and Push Docker Image (tagged with commit SHA and `latest`). + - Trigger Deployment (Portainer Webhook). + +### 3. Portainer & Swarm Configuration +- **Stack Definition:** A `docker-compose` style file for Swarm. +- **Secrets Management:** + - Registry Credentials (if private). + - Environment variables (if any, e.g., API endpoints). +- **Update Mechanism:** Webhook URL provided by Portainer Service. + +## Required Configuration & Secrets +To proceed, we will need to define: +1. **Registry URL:** `gitea.blyzer.com.br` +2. **Image Name:** `gitea.blyzer.com.br/blyzer/comfi` +3. **Portainer Webhook:** The URL Portainer provides to trigger a service update. + +### Secrets (Gitea) +Set these in your Gitea repository settings (Settings > Actions > Secrets): +- `REGISTRY_USERNAME`: Your Gitea username. +- `REGISTRY_TOKEN`: Your Gitea password or token. +- `PORTAINER_WEBHOOK`: The full webhook URL from Portainer. +- `API_KEY`: (Optional) Google GenAI API key. + +## Directives +- **Conventions:** Follow existing TypeScript and React patterns. +- **Safety:** Do not commit `.env` files. +- **Style:** Maintain the clean, dashboard-style UI. diff --git a/components/AIChatAssistant.tsx b/components/AIChatAssistant.tsx index a1f310d..60afccf 100644 --- a/components/AIChatAssistant.tsx +++ b/components/AIChatAssistant.tsx @@ -20,6 +20,10 @@ interface Message { } export const AIChatAssistant: React.FC = ({ userName, contextData }) => { + if (!process.env.API_KEY) { + return null; + } + const [isOpen, setIsOpen] = useState(false); const [isTyping, setIsTyping] = useState(false); const [inputValue, setInputValue] = useState(''); diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..55aa5dd --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,12 @@ +version: '3.8' + +services: + comfi-app: + build: . + image: gitea.blyzer.com.br/blyzer/comfi:latest + container_name: comfi-dashboard + ports: + - "8080:8080" + environment: + - NODE_ENV=production + restart: unless-stopped