bd78fd9fbe
Modulos de restauracion: - bootstrap: instala yq, age y dependencias base (curl, wget, git, nano, gpg) - ssh: descifra e instala claves SSH desde secrets/sshKeys.tar.gz.age - registry: aplica paquetes apt/snap/flatpak, dotfiles, servicios y configs Docker - thunderbird: instala Thunderbird snap y restaura perfil desde ZIP - claudeCode: configura repositorio apt de Anthropic e instala claude-code - easyEffects: restaura configuracion y presets desde ZIP - wireplumber: restaura dispositivo Bluetooth por defecto y perfiles de audio - cups: restaura impresoras y drivers PPD desde ZIP Scripts de captura (correr antes de push): - scripts/encryptSsh.sh: cifra ~/.ssh con age - scripts/thunderbird/capture.sh: captura perfil de Thunderbird snap - scripts/easyEffects/capture.sh: captura config de EasyEffects flatpak - scripts/wireplumber/capture.sh: captura estado de WirePlumber - scripts/cups/capture.sh: captura impresoras CUPS y PPDs (requiere sudo) Registro de aplicaciones (config/registry.yaml): - 9 paquetes apt, 1 snap (dbeaver-ce), 22 flatpaks incluyendo VSCodium, Bitwarden, Inkscape, LibreOffice, OBS Studio, Nextcloud Desktop, entre otros Secretos incluidos: - secrets/sshKeys.tar.gz.age: claves SSH cifradas con age - secrets/thunderbirdProfile.zip: perfil de Thunderbird sin emails ni cache - secrets/easyEffectsConfig.zip: ajustes y presets de salida de audio - secrets/wireplumberState.zip: estado de audio incluyendo auriculares Bluetooth - secrets/cupsConfig.zip: 5 impresoras configuradas con sus drivers Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
147 lines
4.4 KiB
Markdown
147 lines
4.4 KiB
Markdown
# Guía de estilo — STP
|
|
|
|
## Nomenclatura: camelCase sin excepciones
|
|
|
|
Todo identificador del proyecto usa camelCase. No se usa guión bajo (`_`) ni guión (`-`) en nombres de variables, funciones o archivos Bash.
|
|
|
|
| Tipo | Correcto | Incorrecto |
|
|
|------|----------|------------|
|
|
| Variable local | `packageName` | `package_name`, `pkg` |
|
|
| Variable exportada | `stpRoot`, `verbose` | `STP_ROOT`, `VERBOSE` |
|
|
| Constante (`readonly`) | `readonly packagesConfig` | `readonly PACKAGES_CONFIG` |
|
|
| Función | `installAptPackages()` | `install_apt_packages()` |
|
|
| Función privada | `log::emit` | `log::_emit`, `_emit` |
|
|
| Archivo Bash | `encryptSsh.sh` | `encrypt-ssh.sh`, `encrypt_ssh.sh` |
|
|
|
|
Los nombres de archivos YAML (`packages.yaml`, `audio.yaml`) son palabras simples y no requieren separador.
|
|
|
|
---
|
|
|
|
## Clean Code — Robert C. Martin
|
|
|
|
### Una función, una responsabilidad
|
|
|
|
Cada función hace exactamente una cosa. Un bloque de código que necesita un comentario para explicarse debe convertirse en una función con un nombre descriptivo.
|
|
|
|
```bash
|
|
# MAL — lógica mezclada con comentario explicativo
|
|
if apt-cache show age &>/dev/null 2>&1; then
|
|
sudo apt-get install -y age # instala desde apt si está disponible
|
|
else
|
|
# descarga binario de GitHub...
|
|
fi
|
|
|
|
# BIEN — la intención es legible sin comentarios
|
|
if ageIsAvailableInApt; then
|
|
installAgeFromApt
|
|
else
|
|
installAgeFromGithub
|
|
fi
|
|
```
|
|
|
|
### Nombres completos, sin abreviaciones
|
|
|
|
```bash
|
|
# MAL
|
|
for pkg in "${packages[@]}"; do ...
|
|
for svc in "${services[@]}"; do ...
|
|
|
|
# BIEN
|
|
for packageName in "${packages[@]}"; do ...
|
|
for serviceName in "${services[@]}"; do ...
|
|
```
|
|
|
|
Palabras prohibidas como nombre de variable: `pkg`, `svc`, `src`, `dest`, `dir`, `tmp`, `cfg`, `val`, `ret`, `f`, `i` (salvo índices numéricos en bucles simples).
|
|
|
|
### Predicados como preguntas
|
|
|
|
Las funciones booleanas se nombran como preguntas que responden verdadero o falso:
|
|
|
|
```bash
|
|
pipewireIsEnabled() # ¿PipeWire está habilitado en la config?
|
|
isPpaAlreadyAdded() # ¿el PPA ya fue registrado en sources.list?
|
|
dotfilesDirectoryIsEmpty() # ¿no hay dotfiles para desplegar?
|
|
```
|
|
|
|
### Comentarios solo para el PORQUÉ
|
|
|
|
El código expresa el QUÉ. Solo se agrega un comentario cuando el PORQUÉ no es evidente: una restricción externa, una solución provisional, un comportamiento sorpresivo.
|
|
|
|
```bash
|
|
# MAL — el comentario dice lo mismo que el código
|
|
# Verifica si el PPA ya está en sources.list.d
|
|
isPpaAlreadyAdded "$ppaAddress" && continue
|
|
|
|
# BIEN — el código habla por sí mismo; el comentario solo si hay un "porqué" no obvio
|
|
```
|
|
|
|
---
|
|
|
|
## Código funcional sin modo simulación
|
|
|
|
No existe `--dry-run`. El sistema es **idempotente**: verifica el estado actual antes de actuar y omite lo que ya está configurado.
|
|
|
|
```bash
|
|
# Antes de instalar un paquete
|
|
util::isAptInstalled "$packageName" && continue
|
|
|
|
# Antes de agregar un PPA
|
|
isPpaAlreadyAdded "$ppaAddress" && continue
|
|
|
|
# Antes de instalar una clave SSH
|
|
[[ -f "$destination" ]] && { log::warn "Ya existe: $keyFilename"; return 1; }
|
|
```
|
|
|
|
Ejecutar el STP dos veces produce exactamente el mismo resultado que ejecutarlo una vez.
|
|
|
|
---
|
|
|
|
## Agregar una nueva configuración al sistema
|
|
|
|
La forma principal de agregar algo al STP es agregar una entrada a `config/registry.yaml`. No se necesita crear un módulo nuevo para la mayoría de los casos.
|
|
|
|
```yaml
|
|
# Basta con agregar una línea a la lista:
|
|
- id: neovim
|
|
type: apt
|
|
|
|
# La próxima ejecución de stp.sh la detecta y aplica
|
|
```
|
|
|
|
Tipos disponibles en el registro: `ppa`, `apt`, `snap`, `flatpak`, `dotfile`, `service`, `pipewire`, `video`.
|
|
|
|
Solo creá un módulo nuevo cuando la configuración requiera pasos que ningún tipo del registro puede manejar (compilación desde fuente, instaladores externos, configuración interactiva, etc.).
|
|
|
|
---
|
|
|
|
## Estructura de un módulo
|
|
|
|
```bash
|
|
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
source "$stpRoot/lib/log.sh"
|
|
source "$stpRoot/lib/utils.sh"
|
|
source "$stpRoot/lib/yaml.sh" # solo si el módulo lee YAML
|
|
|
|
readonly nombreConfig="$stpRoot/config/nombre.yaml"
|
|
|
|
# Funciones auxiliares específicas (las más pequeñas y concretas)
|
|
helperEspecifico() { ... }
|
|
|
|
# Funciones principales que usan las auxiliares
|
|
hacerAlgo() {
|
|
log::info "Descripción breve..."
|
|
helperEspecifico
|
|
log::ok "Completado"
|
|
}
|
|
|
|
# Verificación inicial: salir si no hay configuración
|
|
if [[ ! -f "$nombreConfig" ]]; then
|
|
log::info "Sin configuración para este módulo, salteando"
|
|
exit 0
|
|
fi
|
|
|
|
# Punto de entrada al final del archivo
|
|
hacerAlgo
|
|
```
|