diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..1b1c4b8 --- /dev/null +++ b/.env.example @@ -0,0 +1,59 @@ +# Ambiente local — Sistema de Chamados +# Copie este arquivo para `.env` e preencha os valores sensíveis. +# Nunca faça commit de `.env` com segredos reais. + +# Convex +CONVEX_DEPLOYMENT=anonymous:anonymous-sistema-de-chamados +NEXT_PUBLIC_CONVEX_URL=http://127.0.0.1:3210 +CONVEX_SYNC_SECRET=dev-sync-secret + +# Next.js / App URL +NEXT_PUBLIC_APP_URL=http://localhost:3000 + +# Better Auth +# Gere um segredo forte (ex.: `openssl rand -hex 32`) +BETTER_AUTH_SECRET=change-me +BETTER_AUTH_URL=http://localhost:3000 + +# Banco de dados (Prisma) +DATABASE_URL=file:./prisma/db.sqlite + +# Provisionamento e inventário de máquinas +# Segredo obrigatório para registrar/atualizar máquinas (Convex) +MACHINE_PROVISIONING_SECRET=change-me-provisioning +# Tempo de vida do token de máquina (ms) — padrão 30 dias +MACHINE_TOKEN_TTL_MS=2592000000 +# Opcional: segredo dedicado para webhook do FleetDM (senão usa o de provisionamento) +FLEET_SYNC_SECRET= + +# SMTP (envio de e-mails) +SMTP_ADDRESS= +SMTP_PORT=465 +SMTP_DOMAIN= +SMTP_USERNAME= +SMTP_PASSWORD= +SMTP_AUTHENTICATION=login +SMTP_ENABLE_STARTTLS_AUTO=false +SMTP_TLS=true +MAILER_SENDER_EMAIL="Suporte " + +# Alertas (actions do Convex) +# Hora local (America/Sao_Paulo) para rodar alertas automáticos +ALERTS_LOCAL_HOUR=8 + +# Seeds e sincronizações auxiliares +SYNC_TENANT_ID=tenant-atlas +SYNC_DEFAULT_ASSIGNEE=agent@example.com +SEED_TENANT_ID=tenant-atlas +SEED_ADMIN_PASSWORD=admin123 +SEED_AGENT_PASSWORD=agent123 +SEED_USER_TENANT=tenant-atlas +SEED_USER_EMAIL= +SEED_USER_PASSWORD= +SEED_USER_NAME= +SEED_USER_ROLE=admin + +# Desenvolvimento Desktop (Tauri/Vite) +# Em redes locais, defina o IP do host para HMR. +TAURI_DEV_HOST= + diff --git a/.github/workflows/ci-cd-web-desktop.yml b/.github/workflows/ci-cd-web-desktop.yml new file mode 100644 index 0000000..254e51a --- /dev/null +++ b/.github/workflows/ci-cd-web-desktop.yml @@ -0,0 +1,97 @@ +name: CI/CD Web + Desktop + +on: + push: + branches: [ main ] + tags: + - 'v*.*.*' + +env: + APP_DIR: /srv/apps/sistema + VPS_UPDATES_DIR: /var/www/updates + +jobs: + deploy: + name: Deploy (VPS Linux) + if: ${{ startsWith(github.ref, 'refs/heads/') }} + runs-on: [ self-hosted, linux, vps ] + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: 9 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'pnpm' + + - name: Sync workspace to APP_DIR + run: | + mkdir -p "$APP_DIR" + rsync -az --delete --exclude '.git' --exclude '.next' ./ "$APP_DIR"/ + + - name: Install and build (Next.js) + run: | + cd "$APP_DIR" + corepack enable || true + pnpm install --frozen-lockfile + pnpm prisma:generate + pnpm build + + - name: Optional Swarm deploy (stack.yml) + if: ${{ hashFiles(format('{0}/stack.yml', env.APP_DIR)) != '' }} + run: | + cd "$APP_DIR" + docker stack deploy --with-registry-auth -c stack.yml sistema + + desktop_release: + name: Desktop Release (Windows) + if: ${{ startsWith(github.ref, 'refs/tags/v') }} + runs-on: [ self-hosted, windows, desktop ] + defaults: + run: + working-directory: apps/desktop + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: 9 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'pnpm' + + - name: Install deps (desktop) + run: pnpm install --frozen-lockfile + + - name: Build with Tauri + uses: tauri-apps/tauri-action@v0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} + TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} + with: + projectPath: apps/desktop + + - name: Upload latest.json + bundles to VPS + uses: appleboy/scp-action@v0.1.7 + with: + host: ${{ secrets.VPS_HOST }} + username: ${{ secrets.VPS_USER }} + key: ${{ secrets.VPS_SSH_KEY }} + source: | + **/bundle/**/latest.json + **/bundle/**/* + target: ${{ env.VPS_UPDATES_DIR }} + overwrite: true + diff --git a/.gitignore b/.gitignore index 332964c..a5fd773 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,8 @@ yarn-error.log* # env files (can opt-in for committing if needed) .env* +!.env.example +!apps/desktop/.env.example # vercel .vercel diff --git a/README.md b/README.md index 4ffff10..c3c0667 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Aplicação Next.js 15 com Convex e Better Auth para gestão de tickets da Rever ```bash pnpm install ``` -2. Ajuste o arquivo `.env` (ou crie a partir do exemplo) e confirme os valores de: +2. Ajuste o arquivo `.env` (ou crie a partir de `.env.example`) e confirme os valores de: - `NEXT_PUBLIC_CONVEX_URL` (gerado pelo Convex Dev) - `BETTER_AUTH_SECRET`, `BETTER_AUTH_URL`, `DATABASE_URL` 3. Aplique as migrações e gere o client Prisma: @@ -42,6 +42,12 @@ Aplicação Next.js 15 com Convex e Better Auth para gestão de tickets da Rever > Se o CLI perguntar sobre configuração do projeto Convex, escolha criar um novo deployment local (opção padrão) e confirme. As credenciais são armazenadas em `.convex/` automaticamente. +### Variáveis de ambiente + +- Exemplo na raiz: `.env.example` — copie para `.env` e preencha segredos. +- App Desktop: `apps/desktop/.env.example` — copie para `apps/desktop/.env` e ajuste `VITE_APP_URL`. +- Nunca faça commit de arquivos `.env` com valores reais (já ignorados em `.gitignore`). + ## Scripts úteis - `pnpm lint` — ESLint com as regras do projeto. diff --git a/apps/desktop/.env.example b/apps/desktop/.env.example new file mode 100644 index 0000000..e6b6e4b --- /dev/null +++ b/apps/desktop/.env.example @@ -0,0 +1,10 @@ +# Ambiente local do App Desktop (Vite/Tauri) +# Copie para `apps/desktop/.env` e ajuste. + +# URL da aplicação web (Next.js) que será carregada dentro do app desktop. +VITE_APP_URL=http://localhost:3000 + +# Opcional: IP do host para desenvolvimento com HMR fora do localhost +# Ex.: 192.168.0.10 +TAURI_DEV_HOST= + diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 1b5ff34..d275163 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,3 +1,6 @@ +packages: + - . + ignoredBuiltDependencies: - '@prisma/client' - '@prisma/engines' diff --git a/stack.yml b/stack.yml new file mode 100644 index 0000000..31324c6 --- /dev/null +++ b/stack.yml @@ -0,0 +1,77 @@ +version: "3.8" + +services: + web: + image: node:20-bullseye + working_dir: /app + command: > + bash -lc "corepack enable \ + && corepack prepare pnpm@9 --activate \ + && pnpm install --frozen-lockfile \ + && pnpm prisma:generate \ + && npx prisma migrate deploy \ + && pnpm build \ + && pnpm start -p 3000" + volumes: + - ./:/app + - sistema_db:/app/data + environment: + NODE_ENV: "production" + # Mantém o SQLite fora do repositório + DATABASE_URL: "file:/app/data/db.sqlite" + deploy: + mode: replicated + replicas: 1 + placement: + constraints: + - node.role == manager + labels: + - traefik.enable=true + - traefik.docker.network=traefik_public + - traefik.http.routers.sistema_web.rule=Host(`tickets.esdrasrenan.com.br`) + - traefik.http.routers.sistema_web.entrypoints=websecure + - traefik.http.routers.sistema_web.tls=true + - traefik.http.routers.sistema_web.tls.certresolver=le + - traefik.http.services.sistema_web.loadbalancer.server.port=3000 + networks: + - traefik_public + + convex: + image: node:20-bullseye + working_dir: /app + command: > + bash -lc "corepack enable \ + && corepack prepare pnpm@9 --activate \ + && pnpm install --frozen-lockfile \ + && set -a && . ./.env && set +a \ + && pnpm convex:dev --port 3210 --hostname 0.0.0.0" + volumes: + - ./:/app + - convex_data:/root/.convex + environment: + NODE_ENV: "production" + deploy: + mode: replicated + replicas: 1 + placement: + constraints: + - node.role == manager + labels: + - traefik.enable=true + - traefik.docker.network=traefik_public + - traefik.http.routers.sistema_convex.rule=Host(`convex.esdrasrenan.com.br`) + - traefik.http.routers.sistema_convex.entrypoints=websecure + - traefik.http.routers.sistema_convex.tls=true + - traefik.http.routers.sistema_convex.tls.certresolver=le + - traefik.http.services.sistema_convex.loadbalancer.server.port=3210 + networks: + - traefik_public + +volumes: + sistema_db: + convex_data: + +networks: + traefik_public: + external: true +