# Capability: deploy

Deploy completo de apps Go/C++/Capacitor a destinos diversos: VPS remotos via SSH+systemd+rsync, VPS con Docker+Traefik+Coolify, Windows Desktop via cross-compile WSL2->mingw-w64, emuladores Android. Cubre setup inicial (vps_setup_app, generate_dockerfile, traefik dynamic), deploys continuos (rsync_deploy + systemd_restart + wait_for_http), webhooks Gitea, y health checks.

## Funciones

| ID | Firma | Que hace |
|---|---|---|
| `compile_cpp_app_bash_pipelines` | `compile_cpp_app(app_name?: string) -> void` | Pipeline que resuelve la app C++ desde el nombre o CWD, la cross-compila para Windows con mingw-w64, y despliega el .exe al escritorio de Windows. Composicion de resolve_cpp_app_dir + build_cpp_windows + deploy_cpp_exe_to_windows. |
| `deploy_app_go_infra` | `func DeployApp(appDir string, imageName string, port int, envVars map[string]string) (string, error)` | Orquesta el deploy completo de una app Go en Docker. Pasos: genera Dockerfile, lo escribe a disco, construye la imagen y lanza el contenedor en modo detach con port mapping. Retorna el container ID. |
| `deploy_app_remote_go_infra` | `func DeployAppRemote(conn SSHConn, cfg DeployConfig) error` | Orquesta el deploy continuo de una app a un VPS: verifica SSH, compila localmente, sube binario, reinicia systemd y hace health check. |
| `deploy_capacitor_to_emulator_bash_pipelines` | `deploy_capacitor_to_emulator(app_dir: string, avd_name?: string, package_name?: string) -> void` | Pipeline end-to-end: build Capacitor APK + arranca AVD + instala + opcionalmente lanza la app. Valida que el AVD existe, construye el APK con capacitor_build_apk, arranca el emulador de forma idempotente, instala el APK y lanza la app si se da package_name. Imprime comando logcat sugerido al final. |
| `deploy_cpp_exe_to_windows_bash_infra` | `deploy_cpp_exe_to_windows(app_name: string, app_dir: string) -> void` | Copia el .exe de Windows (compilado por build_cpp_windows) y sus assets al escritorio de Windows /mnt/c/Users/lucas/Desktop/apps/<APP>/. Mata el proceso si esta corriendo (taskkill.exe pre-autorizado), copia DLLs, sincroniza assets/ y enrichers/ con rsync, maneja runtime Python embebido si python_runtime: true en app.md, y copia extras gx-cli. Preserva siempre local_files/ (estado del usuario). |
| `docker_compose_remote_deploy_bash_infra` | `docker_compose_remote_deploy(host: string, remote_dir: string, branch: string, compose_files: string) -> json` | Despliega un stack Docker Compose en un host remoto via SSH. Verifica conectividad, hace git pull del branch indicado, actualiza imagenes con docker-compose pull y levanta/recrea los servicios modificados con docker-compose up -d. Soporta compose files adicionales. Retorna JSON con status, containers corriendo y duracion. |
| `dockerize_app_bash_pipelines` | `dockerize_app(app_name: string, [--domain DOMAIN], [--port PORT], [--ssh-host HOST], [--remote-dir DIR], [--basic-auth USER:PASS], [--no-auth], [--no-gzip], [--env KEY=VAL]..., [--volume NAME], [--build-cmd CMD], [--standalone], [--dry-run]) -> json` | Empaqueta una app Go del registry para deploy a VPS organic-machine via Docker + Traefik + Coolify. Genera Dockerfile multi-stage, docker-compose.yml, traefik-dynamic.yml con basicAuth opcional y gzip, sube via rsync al VPS y arranca el stack remoto. Replica el patron de apps/registry_api/. |
| `generate_compose_traefik_go_infra` | `func GenerateComposeTraefik(cfg ComposeTraefikConfig) string` | Genera el texto YAML de un docker-compose.yml para una app Go desplegada behind Traefik + Coolify. Replica el patron de apps/registry_api/docker-compose.yml. Determinista: orden de EnvVars sigue el orden de entrada. |
| `generate_dockerfile_go_infra` | `func GenerateDockerfile(binaryName string, port int, envVars map[string]string) string` | Genera el texto de un Dockerfile multi-stage para una app Go. Stage build con golang:1.23-alpine, stage final con alpine:latest. Incluye ENV vars del map con orden determinista. Funcion pura sin I/O. |
| `generate_traefik_dynamic_go_infra` | `func GenerateTraefikDynamic(cfg TraefikDynamicConfig) string` | Genera el texto YAML de un traefik-dynamic.yml para el file provider de Traefik (Coolify). Replica el patron de apps/registry_api/traefik-dynamic.yml con routers HTTP/HTTPS, redirect, basicAuth opcional y gzip opcional. |
| `gitea_create_webhook_bash_infra` | `gitea_create_webhook(owner: string, repo: string, target_url: string, secret?: string) -> json` | Crea un webhook de push en un repositorio Gitea. El webhook notifica a target_url en cada push. |
| `go_build_binary_go_infra` | `func GoBuildBinary(projectDir, outputPath string, ldflags string, tags string) error` | Compila un binario Go desde un directorio de proyecto. Si ldflags está vacío usa -s -w (strip debug). Si outputPath está vacío usa build/{dirname} dentro del projectDir. Ejecuta con CGO_ENABLED=0. |
| `rsync_deploy_bash_infra` | `rsync_deploy(local_dir: string, ssh_alias: string, remote_dir: string) -> json` | Sincroniza un directorio local a un host remoto via rsync+SSH. Excluye archivos de desarrollo y bases de datos locales. Crea el directorio remoto si no existe. |
| `setup_registry_api_bash_infra` | `setup_registry_api(ssh_host: string, api_token: string, basic_auth_user: string, basic_auth_pass: string) -> json` | Deploy completo de registry_api en VPS con Docker + Traefik (Coolify proxy). Sincroniza el repo via rsync, genera el hash bcrypt para basicAuth, sube el traefik-dynamic.yml, crea el .env con el token, hace docker compose build+up y verifica el health check. |
| `setup_vps_app_go_infra` | `func SetupVPSApp(conn SSHConn, cfg DeployConfig) error` | Orquesta el setup inicial de una app en un VPS remoto: verifica SSH, crea dirs y usuario, sube binario, instala systemd unit y hace health check. |
| `stop_app_go_infra` | `func StopApp(containerName string, removeImage bool) error` | Para y elimina el contenedor de una app desplegada. Si removeImage es true elimina también la imagen Docker. containerName debe coincidir con el imageName usado en deploy_app. |
| `systemd_generate_unit_go_infra` | `func SystemdGenerateUnit(name, execStart, workDir, user string, env map[string]string) string` | Genera el texto de un archivo .service de systemd para una app. Incluye restart automático y env vars en orden determinista. |
| `systemd_install_go_infra` | `func SystemdInstall(conn SSHConn, unitName, unitContent string) error` | Sube un unit file al host remoto, hace daemon-reload, enable y restart. Idempotente: reemplaza si el unit ya existe. |
| `vps_setup_app_go_infra` | `func VPSSetupApp(conn SSHConn, appName, remoteDir, serviceUser string) error` | Prepara un host remoto para recibir una app: crea directorios, usuario de servicio y asigna ownership. |
| `wait_for_http_bash_infra` | `wait_for_http <url> [timeout_seconds] [interval_seconds]` | Hace polling a una URL HTTP/HTTPS hasta recibir respuesta 2xx o agotar el timeout. Util en deploys, post-restart de servicios y smoke tests. |
| `write_dockerfile_go_infra` | `func WriteDockerfile(dir, content string) (string, error)` | Escribe content en dir/Dockerfile. Crea el directorio si no existe. Retorna el path absoluto del archivo escrito. Compañera impura de generate_dockerfile. |


## Ejemplo canonico

### App Go a VPS con Docker+Traefik

```bash
./fn run dockerize_app my_api \
  --domain my_api.organic-machine.com \
  --port 8080 \
  --ssh-host organic-machine \
  --remote-dir /srv/coolify/my_api \
  --basic-auth admin:supersecret
```

Empaqueta `apps/my_api/` (Go), genera Dockerfile multistage + docker-compose + traefik-dynamic con basicAuth, sube via rsync, levanta el stack remoto.

### App Go a VPS con systemd (sin Docker)

```bash
# Setup inicial
./fn run setup_vps_app --host organic-machine --app my_api --port 8080

# Deploy continuo (build local + rsync + restart systemd + health check)
./fn run deploy_app_remote --host organic-machine --app my_api
```

### App C++ a Windows Desktop desde WSL2

```bash
./fn run compile_cpp_app registry_dashboard
# Cross-compila con mingw-w64 + deploya .exe + DLLs + assets a /mnt/c/Users/lucas/Desktop/apps/registry_dashboard/
```

## Fronteras

- **NO orquesta CI/CD pipelines**. Si necesitas pipelines completas (GitHub Actions, Gitea Actions), construye yaml a mano.
- **NO maneja secretos rotativos**. Pasa secretos via env vars; rotacion es manual.
- **NO hace blue-green ni canary**. Cada deploy es un swap directo. Si necesitas zero-downtime sofisticado, usa Traefik con multiple instancias y label-based routing manual.
- **NO incluye monitoring post-deploy**. Health check inicial sí; observabilidad continua es responsabilidad del operador (ver grupo `registry` para auditoria).
