# Deploy & Flujo de ramas — EnterFarmaPlus

Guía corta para no re-divergir ni romper prod. Server de producción: **5.161.118.178**, corre la rama **`main`** (stack Docker; container FPM `fpm_softlte_org_pe`, path `/var/www/html/farmacia`).

---

## 1. Flujo de ramas (regla de oro)

- Desarrollás en una **feature branch** por vertical: `feat/clinica`, `feat/veterinary`, etc.
- Para publicar un bloque terminado:
  ```bash
  git checkout main
  git merge feat/clinica        # main queda = la branch
  # ... deploy (sección 2) ...
  ```
- ❌ **NUNCA** commitees el deploy directo en `main` mientras la feature branch sigue viva (eso las separa).
- Si squasheás una branch a main → **borrala y cortá una nueva desde main** para la próxima tanda. No sigas desarrollando en una branch ya squasheada.
- Para cambios chicos: se puede commitear directo en `main` (= server), pero hacé `git merge main` a las feature branches seguido para mantenerlas al día.

---

## 2. Checklist de deploy (prod)

1. **Buildear el flavor de assets que matchea la rama** antes de commitear:
   - `main` commitea assets **PROD** (minificados) → `npm run prod`.
   - feature branches commitean **DEV** → `npm run development`.
   - (Verificar el flavor de la rama: `git show HEAD:public/js/app.js | wc -l` — ~2 líneas = prod, ~40k = dev.)
2. **Commitear solo el cambio intencional** (`git add <archivos>`, no `git add -A` a ciegas).
3. `git push origin main`
4. En el server, ejecutar el único script de despliegue desde el **host**:
   ```bash
   /usr/local/sbin/deploy-enterfarmaplus
   ```
   El repositorio es un bind mount del host. La Deploy Key read-only vive en
   `/root/.ssh/enterfarmaplus_gitlab_deploy`; no se copia al contenedor.

   El script:
   - bloquea despliegues simultáneos con `flock`;
   - cancela si la rama no es `main` o el árbol Git está sucio;
   - acepta exclusivamente un avance fast-forward desde `origin/main`;
   - instala dependencias Composer, sin ejecutar `npm`;
   - aplica migraciones centrales y de todos los tenants;
   - limpia cachés, reinicia workers y corrige permisos solo de runtime;
   - valida `https://demo.sysfarma.pe/login`;
   - registra commits y resultado en `/var/lib/enterfarmaplus-deploy/` y
     `/var/log/enterfarmaplus-deploy.log`.

   - ⚠️ **NUNCA `route:cache`** (rompe las rutas dinámicas por tenant).
   - ⚠️ **NUNCA `npm` en el server** (los assets van versionados en git).
   - ⚠️ **NUNCA `git reset --hard` como deploy normal**. Si el preflight falla,
     investigar el cambio antes de tocarlo.
5. **Si el cambio toca el schema** (migraciones): correr en **TODOS los tenants**, no solo el nuevo:
   ```bash
   docker exec fpm_softlte_org_pe php artisan tenancy:migrate
   ```
   - Lección (2026-06-30): un vertical (clínica) subió código que consultaba `is_clinic_service` en TODOS los tenants pero solo migró el tenant nuevo → listado de productos caído (500) en los 14 tenants. Regla: **si el código referencia una columna nueva sin gatearla por el flag del giro, la columna debe existir en todos los tenants** → `tenancy:migrate` global. Mejor aún: **gateá la query por el flag** (`if is_clinic / is_veterinary`) para que una columna faltante no tumbe a los demás.
6. **Verificar live** (curl del `<title>`/endpoint, o Playwright).

### Rollback

El script guarda el commit anterior en:

```bash
cat /var/lib/enterfarmaplus-deploy/previous-commit
```

No existe rollback automático porque una migración puede no ser reversible. Ante una
falla, revisar primero `/var/log/enterfarmaplus-deploy.log`, la BD y el alcance del cambio.
Un rollback de código con `git reset --hard` requiere decisión manual y respaldo previo.

### Seguridad

- La Deploy Key de GitLab es solo lectura y permanece en el host.
- No habilitar permisos generales de SSH/`plink` para automatizaciones.
- El password de `root` expuesto durante tareas de soporte debe rotarse. Después,
  migrar a un usuario de deploy con comando forzado o job manual de CI protegido.

---

## 3. Higiene del repo

- **No commitear screenshots/capturas** a la raíz (ya ignorados por `.gitignore`: `/*.png`, `/*.jpg`, etc.). Para temporales usar el scratchpad de la sesión, no la raíz del repo.
- **Migraciones tenant** guardadas/idempotentes (chequear `hasTable`/`hasColumn`) para que sean inertes en tenants donde no aplican.
- Evitar el "stash dance" (stash → checkout → deploy → restore): con el flujo de la sección 1 (merge a main) no hace falta stashear.
