claude-agent-framework 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/README.md +128 -0
  2. package/bin/claude-framework +3 -0
  3. package/framework/agents/design-lead.md +240 -0
  4. package/framework/agents/product-owner.md +179 -0
  5. package/framework/agents/tech-lead.md +226 -0
  6. package/framework/commands/ayuda.md +127 -0
  7. package/framework/commands/a/303/261adir.md +98 -0
  8. package/framework/commands/backup.md +397 -0
  9. package/framework/commands/cambiar.md +110 -0
  10. package/framework/commands/cloud.md +457 -0
  11. package/framework/commands/code.md +142 -0
  12. package/framework/commands/debug.md +334 -0
  13. package/framework/commands/deploy.md +383 -0
  14. package/framework/commands/deshacer.md +120 -0
  15. package/framework/commands/estado.md +218 -0
  16. package/framework/commands/explica.md +227 -0
  17. package/framework/commands/feature.md +120 -0
  18. package/framework/commands/git.md +427 -0
  19. package/framework/commands/historial.md +202 -0
  20. package/framework/commands/learn.md +408 -0
  21. package/framework/commands/movil.md +245 -0
  22. package/framework/commands/nuevo.md +118 -0
  23. package/framework/commands/plan.md +134 -0
  24. package/framework/commands/prd.md +113 -0
  25. package/framework/commands/probar.md +148 -0
  26. package/framework/commands/revisar.md +208 -0
  27. package/framework/commands/seeds.md +230 -0
  28. package/framework/commands/seguridad.md +226 -0
  29. package/framework/commands/tasks.md +157 -0
  30. package/framework/skills/architecture/algorithms.md +970 -0
  31. package/framework/skills/architecture/clean-code.md +1080 -0
  32. package/framework/skills/architecture/design-patterns.md +1984 -0
  33. package/framework/skills/architecture/functional-programming.md +972 -0
  34. package/framework/skills/architecture/solid.md +991 -0
  35. package/framework/skills/cloud/cloud-aws.md +848 -0
  36. package/framework/skills/cloud/cloud-azure.md +931 -0
  37. package/framework/skills/cloud/cloud-gcp.md +848 -0
  38. package/framework/skills/cloud/message-queues.md +1229 -0
  39. package/framework/skills/core/accessibility.md +401 -0
  40. package/framework/skills/core/api.md +474 -0
  41. package/framework/skills/core/authentication.md +306 -0
  42. package/framework/skills/core/authorization.md +388 -0
  43. package/framework/skills/core/background-jobs.md +341 -0
  44. package/framework/skills/core/caching.md +473 -0
  45. package/framework/skills/core/code-review.md +341 -0
  46. package/framework/skills/core/controllers.md +290 -0
  47. package/framework/skills/core/cua.md +285 -0
  48. package/framework/skills/core/documentation.md +472 -0
  49. package/framework/skills/core/file-uploads.md +351 -0
  50. package/framework/skills/core/hotwire-native.md +296 -0
  51. package/framework/skills/core/hotwire.md +278 -0
  52. package/framework/skills/core/i18n.md +334 -0
  53. package/framework/skills/core/imports-exports.md +750 -0
  54. package/framework/skills/core/infrastructure.md +337 -0
  55. package/framework/skills/core/models.md +228 -0
  56. package/framework/skills/core/notifications.md +672 -0
  57. package/framework/skills/core/payments.md +581 -0
  58. package/framework/skills/core/performance.md +361 -0
  59. package/framework/skills/core/rails-scaffold.md +131 -0
  60. package/framework/skills/core/search.md +518 -0
  61. package/framework/skills/core/security.md +565 -0
  62. package/framework/skills/core/seeds.md +307 -0
  63. package/framework/skills/core/seo.md +542 -0
  64. package/framework/skills/core/testing.md +393 -0
  65. package/framework/skills/core/views.md +260 -0
  66. package/framework/skills/core/websockets.md +564 -0
  67. package/framework/skills/data/advanced-sql.md +1204 -0
  68. package/framework/skills/data/nosql.md +1141 -0
  69. package/framework/skills/devops/containers-advanced.md +1237 -0
  70. package/framework/skills/devops/debugging.md +834 -0
  71. package/framework/skills/devops/git-workflow.md +752 -0
  72. package/framework/skills/devops/networking.md +932 -0
  73. package/framework/skills/devops/shell-scripting.md +1132 -0
  74. package/framework/sub-agents/architecture-patterns-agent.md +1450 -0
  75. package/framework/sub-agents/cloud-agent.md +677 -0
  76. package/framework/sub-agents/data.md +504 -0
  77. package/framework/sub-agents/debugging-agent.md +554 -0
  78. package/framework/sub-agents/devops.md +483 -0
  79. package/framework/sub-agents/docs.md +176 -0
  80. package/framework/sub-agents/frontend-dev.md +349 -0
  81. package/framework/sub-agents/git-workflow-agent.md +697 -0
  82. package/framework/sub-agents/integrations.md +630 -0
  83. package/framework/sub-agents/native-dev.md +434 -0
  84. package/framework/sub-agents/qa.md +138 -0
  85. package/framework/sub-agents/rails-dev.md +375 -0
  86. package/framework/sub-agents/security.md +526 -0
  87. package/framework/sub-agents/ui.md +437 -0
  88. package/framework/sub-agents/ux.md +284 -0
  89. package/framework/templates/api-spec.md +500 -0
  90. package/framework/templates/component-spec.md +248 -0
  91. package/framework/templates/feature.json +13 -0
  92. package/framework/templates/model-spec.md +318 -0
  93. package/framework/templates/prd-template.md +80 -0
  94. package/framework/templates/task-plan.md +122 -0
  95. package/framework/templates/task-user-story.md +52 -0
  96. package/framework/templates/technical-spec.md +260 -0
  97. package/framework/templates/user-story.md +95 -0
  98. package/package.json +42 -0
  99. package/project-templates/CLAUDE.md +42 -0
  100. package/project-templates/contexts/architecture.md +25 -0
  101. package/project-templates/contexts/conventions.md +46 -0
  102. package/project-templates/contexts/design-system.md +47 -0
  103. package/project-templates/contexts/requirements.md +38 -0
  104. package/project-templates/contexts/stack.md +30 -0
  105. package/project-templates/history/active/models.md +11 -0
  106. package/project-templates/history/changelog.md +15 -0
  107. package/project-templates/workspace/.gitkeep +0 -0
  108. package/src/cli.js +52 -0
  109. package/src/init.js +104 -0
  110. package/src/status.js +75 -0
  111. package/src/update.js +88 -0
@@ -0,0 +1,1132 @@
1
+ # Skill: Shell Scripting
2
+
3
+ ## Purpose
4
+
5
+ Automatizar tareas repetitivas y operaciones de DevOps usando Bash scripting para proyectos Rails.
6
+
7
+ ## Basics
8
+
9
+ ### Variables
10
+
11
+ ```bash
12
+ #!/bin/bash
13
+
14
+ # Asignación (sin espacios alrededor de =)
15
+ NAME="myapp"
16
+ VERSION="1.0.0"
17
+ COUNT=42
18
+
19
+ # Uso de variables
20
+ echo "Deploying $NAME version $VERSION"
21
+ echo "Deploying ${NAME} version ${VERSION}" # Más explícito
22
+
23
+ # Variables de solo lectura
24
+ readonly DB_NAME="production"
25
+
26
+ # Variables por defecto
27
+ RAILS_ENV="${RAILS_ENV:-development}" # development si no está definida
28
+ PORT="${PORT:=3000}" # Asigna 3000 si no está definida
29
+
30
+ # Resultado de comando
31
+ CURRENT_DATE=$(date +%Y-%m-%d)
32
+ GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
33
+
34
+ # Aritmética
35
+ COUNT=$((COUNT + 1))
36
+ TOTAL=$((10 * 5))
37
+ ```
38
+
39
+ ### Arrays
40
+
41
+ ```bash
42
+ #!/bin/bash
43
+
44
+ # Declarar array
45
+ SERVERS=("web1" "web2" "web3")
46
+ TASKS=("migrate" "assets" "restart")
47
+
48
+ # Acceder a elementos
49
+ echo "${SERVERS[0]}" # web1
50
+ echo "${SERVERS[@]}" # Todos los elementos
51
+ echo "${#SERVERS[@]}" # Número de elementos (3)
52
+ echo "${SERVERS[@]:1:2}" # Slice: web2 web3
53
+
54
+ # Añadir elementos
55
+ SERVERS+=("web4")
56
+
57
+ # Iterar
58
+ for server in "${SERVERS[@]}"; do
59
+ echo "Deploying to $server"
60
+ done
61
+
62
+ # Array asociativo (Bash 4+)
63
+ declare -A CONFIG
64
+ CONFIG[host]="localhost"
65
+ CONFIG[port]="5432"
66
+ CONFIG[database]="myapp_production"
67
+
68
+ echo "Connecting to ${CONFIG[host]}:${CONFIG[port]}"
69
+ ```
70
+
71
+ ### Strings
72
+
73
+ ```bash
74
+ #!/bin/bash
75
+
76
+ STR="Hello World"
77
+
78
+ # Longitud
79
+ echo "${#STR}" # 11
80
+
81
+ # Substring
82
+ echo "${STR:0:5}" # Hello
83
+ echo "${STR:6}" # World
84
+
85
+ # Reemplazo
86
+ echo "${STR/World/Rails}" # Hello Rails
87
+ echo "${STR//o/0}" # Hell0 W0rld (todos)
88
+
89
+ # Eliminar patrón
90
+ FILE="app/models/user.rb"
91
+ echo "${FILE%.rb}" # app/models/user (elimina suffix)
92
+ echo "${FILE##*/}" # user.rb (elimina prefix hasta /)
93
+ echo "${FILE%/*}" # app/models (directorio)
94
+
95
+ # Mayúsculas/minúsculas (Bash 4+)
96
+ echo "${STR,,}" # hello world
97
+ echo "${STR^^}" # HELLO WORLD
98
+
99
+ # Verificar si está vacío
100
+ if [[ -z "$VAR" ]]; then
101
+ echo "VAR está vacía"
102
+ fi
103
+
104
+ if [[ -n "$VAR" ]]; then
105
+ echo "VAR tiene valor"
106
+ fi
107
+ ```
108
+
109
+ ## Control Flow
110
+
111
+ ### If/Else
112
+
113
+ ```bash
114
+ #!/bin/bash
115
+
116
+ # Básico
117
+ if [[ $RAILS_ENV == "production" ]]; then
118
+ echo "Production mode"
119
+ elif [[ $RAILS_ENV == "staging" ]]; then
120
+ echo "Staging mode"
121
+ else
122
+ echo "Development mode"
123
+ fi
124
+
125
+ # Operadores de comparación (strings)
126
+ [[ $a == $b ]] # Igual
127
+ [[ $a != $b ]] # Diferente
128
+ [[ $a < $b ]] # Menor (alfabético)
129
+ [[ $a =~ ^[0-9]+$ ]] # Regex match
130
+
131
+ # Operadores de comparación (números)
132
+ [[ $a -eq $b ]] # Igual
133
+ [[ $a -ne $b ]] # Diferente
134
+ [[ $a -lt $b ]] # Menor que
135
+ [[ $a -le $b ]] # Menor o igual
136
+ [[ $a -gt $b ]] # Mayor que
137
+ [[ $a -ge $b ]] # Mayor o igual
138
+
139
+ # Operadores lógicos
140
+ [[ $a && $b ]] # AND
141
+ [[ $a || $b ]] # OR
142
+ [[ ! $a ]] # NOT
143
+
144
+ # Verificar archivos
145
+ [[ -f "$FILE" ]] # Archivo existe
146
+ [[ -d "$DIR" ]] # Directorio existe
147
+ [[ -r "$FILE" ]] # Legible
148
+ [[ -w "$FILE" ]] # Escribible
149
+ [[ -x "$FILE" ]] # Ejecutable
150
+ [[ -s "$FILE" ]] # Tamaño > 0
151
+
152
+ # One-liner
153
+ [[ -f config.yml ]] && echo "Config exists" || echo "Config missing"
154
+ ```
155
+
156
+ ### Case
157
+
158
+ ```bash
159
+ #!/bin/bash
160
+
161
+ case "$COMMAND" in
162
+ start)
163
+ echo "Starting server..."
164
+ rails server -d
165
+ ;;
166
+ stop)
167
+ echo "Stopping server..."
168
+ pkill -f "rails server"
169
+ ;;
170
+ restart)
171
+ $0 stop
172
+ $0 start
173
+ ;;
174
+ status)
175
+ pgrep -f "rails server" && echo "Running" || echo "Stopped"
176
+ ;;
177
+ *)
178
+ echo "Usage: $0 {start|stop|restart|status}"
179
+ exit 1
180
+ ;;
181
+ esac
182
+ ```
183
+
184
+ ### For Loop
185
+
186
+ ```bash
187
+ #!/bin/bash
188
+
189
+ # Lista simple
190
+ for env in development staging production; do
191
+ echo "Environment: $env"
192
+ done
193
+
194
+ # Rango
195
+ for i in {1..5}; do
196
+ echo "Iteration $i"
197
+ done
198
+
199
+ # Rango con paso
200
+ for i in {0..10..2}; do
201
+ echo "Even: $i"
202
+ done
203
+
204
+ # Estilo C
205
+ for ((i=0; i<10; i++)); do
206
+ echo "Index: $i"
207
+ done
208
+
209
+ # Archivos
210
+ for file in app/models/*.rb; do
211
+ echo "Processing $file"
212
+ done
213
+
214
+ # Líneas de archivo
215
+ while IFS= read -r line; do
216
+ echo "Line: $line"
217
+ done < config/servers.txt
218
+
219
+ # Resultado de comando
220
+ for user in $(cat /etc/passwd | cut -d: -f1); do
221
+ echo "User: $user"
222
+ done
223
+ ```
224
+
225
+ ### While Loop
226
+
227
+ ```bash
228
+ #!/bin/bash
229
+
230
+ # Contador
231
+ count=0
232
+ while [[ $count -lt 5 ]]; do
233
+ echo "Count: $count"
234
+ ((count++))
235
+ done
236
+
237
+ # Esperar condición
238
+ while ! pg_isready -h localhost -p 5432; do
239
+ echo "Waiting for PostgreSQL..."
240
+ sleep 2
241
+ done
242
+ echo "PostgreSQL is ready!"
243
+
244
+ # Loop infinito con break
245
+ while true; do
246
+ read -p "Enter command (quit to exit): " cmd
247
+ [[ $cmd == "quit" ]] && break
248
+ eval "$cmd"
249
+ done
250
+
251
+ # Until (opuesto a while)
252
+ until [[ -f /tmp/ready.flag ]]; do
253
+ echo "Waiting for ready flag..."
254
+ sleep 1
255
+ done
256
+ ```
257
+
258
+ ## Funciones
259
+
260
+ ```bash
261
+ #!/bin/bash
262
+
263
+ # Función simple
264
+ greet() {
265
+ echo "Hello, World!"
266
+ }
267
+
268
+ # Función con argumentos
269
+ deploy() {
270
+ local server=$1
271
+ local branch=${2:-main} # Default: main
272
+
273
+ echo "Deploying $branch to $server"
274
+ ssh "$server" "cd /app && git pull origin $branch && bundle install"
275
+ }
276
+
277
+ # Uso
278
+ deploy "web1.example.com" "feature/new-design"
279
+ deploy "web2.example.com" # Usa branch main
280
+
281
+ # Retornar valor (0-255)
282
+ is_production() {
283
+ [[ $RAILS_ENV == "production" ]]
284
+ return $? # 0 si true, 1 si false
285
+ }
286
+
287
+ if is_production; then
288
+ echo "Production checks enabled"
289
+ fi
290
+
291
+ # Retornar string
292
+ get_version() {
293
+ cat VERSION
294
+ }
295
+ VERSION=$(get_version)
296
+
297
+ # Variables locales
298
+ calculate() {
299
+ local result=$(($1 + $2))
300
+ echo $result
301
+ }
302
+ SUM=$(calculate 5 3) # 8
303
+
304
+ # Función con validación
305
+ backup_database() {
306
+ local db_name=$1
307
+ local backup_path=$2
308
+
309
+ if [[ -z "$db_name" ]] || [[ -z "$backup_path" ]]; then
310
+ echo "Usage: backup_database <db_name> <backup_path>" >&2
311
+ return 1
312
+ fi
313
+
314
+ pg_dump "$db_name" > "$backup_path"
315
+ return $?
316
+ }
317
+ ```
318
+
319
+ ## Pipes y Redirección
320
+
321
+ ### Pipes
322
+
323
+ ```bash
324
+ #!/bin/bash
325
+
326
+ # Encadenar comandos
327
+ cat access.log | grep "POST" | wc -l
328
+
329
+ # Múltiples pipes
330
+ ps aux | grep rails | grep -v grep | awk '{print $2}'
331
+
332
+ # Pipe a while
333
+ cat servers.txt | while read server; do
334
+ echo "Checking $server"
335
+ ping -c 1 "$server"
336
+ done
337
+
338
+ # tee: escribir a archivo y stdout
339
+ bundle install 2>&1 | tee install.log
340
+ ```
341
+
342
+ ### Redirección
343
+
344
+ ```bash
345
+ #!/bin/bash
346
+
347
+ # Redireccionar stdout
348
+ echo "Log message" > app.log # Sobrescribir
349
+ echo "Another line" >> app.log # Añadir
350
+
351
+ # Redireccionar stderr
352
+ command 2> error.log # Solo stderr
353
+ command 2>> error.log # Añadir stderr
354
+
355
+ # Ambos a mismo archivo
356
+ command > output.log 2>&1 # stdout y stderr
357
+ command &> output.log # Forma corta (Bash)
358
+
359
+ # Separar stdout y stderr
360
+ command > stdout.log 2> stderr.log
361
+
362
+ # Descartar output
363
+ command > /dev/null # Ignorar stdout
364
+ command 2> /dev/null # Ignorar stderr
365
+ command &> /dev/null # Ignorar todo
366
+
367
+ # Here document
368
+ cat > config.yml <<EOF
369
+ database:
370
+ host: localhost
371
+ port: 5432
372
+ name: $DB_NAME
373
+ EOF
374
+
375
+ # Here string
376
+ grep "error" <<< "$LOG_CONTENT"
377
+
378
+ # Process substitution
379
+ diff <(cat file1.txt) <(cat file2.txt)
380
+ ```
381
+
382
+ ## Comandos Útiles
383
+
384
+ ### grep
385
+
386
+ ```bash
387
+ #!/bin/bash
388
+
389
+ # Búsqueda básica
390
+ grep "error" app.log
391
+ grep -i "error" app.log # Case insensitive
392
+ grep -n "error" app.log # Mostrar números de línea
393
+ grep -c "error" app.log # Contar coincidencias
394
+ grep -v "debug" app.log # Invertir (excluir)
395
+
396
+ # Regex
397
+ grep -E "error|warning" app.log # Extended regex
398
+ grep "user_[0-9]+" app.log # Pattern con números
399
+
400
+ # Archivos
401
+ grep -r "TODO" app/ # Recursivo
402
+ grep -l "class User" app/models/ # Solo nombres de archivo
403
+ grep -L "test" spec/ # Archivos sin match
404
+
405
+ # Contexto
406
+ grep -A 3 "error" app.log # 3 líneas después
407
+ grep -B 3 "error" app.log # 3 líneas antes
408
+ grep -C 3 "error" app.log # 3 líneas antes y después
409
+ ```
410
+
411
+ ### awk
412
+
413
+ ```bash
414
+ #!/bin/bash
415
+
416
+ # Imprimir columnas
417
+ awk '{print $1}' file.txt # Primera columna
418
+ awk '{print $1, $3}' file.txt # Columnas 1 y 3
419
+ awk '{print $NF}' file.txt # Última columna
420
+
421
+ # Con delimitador
422
+ awk -F: '{print $1}' /etc/passwd # Delimitador :
423
+ awk -F',' '{print $2}' data.csv # Delimitador ,
424
+
425
+ # Condiciones
426
+ awk '$3 > 100 {print $1}' data.txt
427
+ awk '/error/ {print}' app.log
428
+
429
+ # Cálculos
430
+ awk '{sum += $1} END {print sum}' numbers.txt
431
+ awk '{count++} END {print count}' file.txt
432
+
433
+ # Variables
434
+ awk -v threshold=100 '$3 > threshold {print}' data.txt
435
+
436
+ # Ejemplo: analizar logs de Rails
437
+ awk '/Completed [45][0-9]{2}/ {print $4, $0}' production.log
438
+ ```
439
+
440
+ ### sed
441
+
442
+ ```bash
443
+ #!/bin/bash
444
+
445
+ # Reemplazar texto
446
+ sed 's/old/new/' file.txt # Primera ocurrencia por línea
447
+ sed 's/old/new/g' file.txt # Todas las ocurrencias
448
+ sed -i 's/old/new/g' file.txt # In-place (modifica archivo)
449
+ sed -i.bak 's/old/new/g' file.txt # Con backup
450
+
451
+ # Eliminar líneas
452
+ sed '/pattern/d' file.txt # Líneas con pattern
453
+ sed '5d' file.txt # Línea 5
454
+ sed '1,10d' file.txt # Líneas 1-10
455
+
456
+ # Insertar/añadir
457
+ sed '3i\New line' file.txt # Insertar antes de línea 3
458
+ sed '3a\New line' file.txt # Añadir después de línea 3
459
+
460
+ # Múltiples comandos
461
+ sed -e 's/foo/bar/g' -e 's/baz/qux/g' file.txt
462
+
463
+ # Ejemplo: actualizar config
464
+ sed -i "s/DB_HOST=.*/DB_HOST=$NEW_HOST/" .env
465
+ ```
466
+
467
+ ### xargs
468
+
469
+ ```bash
470
+ #!/bin/bash
471
+
472
+ # Ejecutar comando con cada línea
473
+ cat files.txt | xargs rm
474
+ find . -name "*.log" | xargs rm
475
+
476
+ # Con placeholder
477
+ cat servers.txt | xargs -I {} ssh {} "uptime"
478
+
479
+ # Paralelo
480
+ cat urls.txt | xargs -P 4 -I {} curl -s {}
481
+
482
+ # Con confirmación
483
+ find . -name "*.tmp" | xargs -p rm
484
+
485
+ # Manejar espacios en nombres
486
+ find . -name "*.rb" -print0 | xargs -0 wc -l
487
+ ```
488
+
489
+ ### find
490
+
491
+ ```bash
492
+ #!/bin/bash
493
+
494
+ # Por nombre
495
+ find . -name "*.rb" # Archivos .rb
496
+ find . -iname "*.rb" # Case insensitive
497
+ find . -name "user*" # Empiezan con user
498
+
499
+ # Por tipo
500
+ find . -type f # Solo archivos
501
+ find . -type d # Solo directorios
502
+
503
+ # Por tiempo
504
+ find . -mtime -7 # Modificados últimos 7 días
505
+ find . -mmin -60 # Modificados última hora
506
+
507
+ # Por tamaño
508
+ find . -size +10M # Mayores de 10MB
509
+ find . -size -1k # Menores de 1KB
510
+
511
+ # Ejecutar comando
512
+ find . -name "*.rb" -exec wc -l {} \;
513
+ find . -name "*.log" -exec rm {} +
514
+
515
+ # Combinaciones
516
+ find app -name "*.rb" -type f -mtime -7
517
+
518
+ # Excluir directorios
519
+ find . -name "*.rb" -not -path "./vendor/*"
520
+ ```
521
+
522
+ ## Script Structure
523
+
524
+ ### Shebang y header
525
+
526
+ ```bash
527
+ #!/bin/bash
528
+ #
529
+ # Script: deploy.sh
530
+ # Description: Deploy Rails application
531
+ # Author: Your Name
532
+ # Date: 2024-01-15
533
+ # Usage: ./deploy.sh [environment]
534
+ #
535
+
536
+ set -euo pipefail # Exit on error, undefined vars, pipe failures
537
+ IFS=$'\n\t' # Safer word splitting
538
+ ```
539
+
540
+ ### Exit codes
541
+
542
+ ```bash
543
+ #!/bin/bash
544
+
545
+ # Códigos estándar
546
+ # 0 = éxito
547
+ # 1 = error general
548
+ # 2 = uso incorrecto
549
+
550
+ deploy() {
551
+ if [[ -z "$1" ]]; then
552
+ echo "Error: Environment required" >&2
553
+ exit 2
554
+ fi
555
+
556
+ if ! ssh "$1" "cd /app && git pull"; then
557
+ echo "Error: Deployment failed" >&2
558
+ exit 1
559
+ fi
560
+
561
+ echo "Deployment successful"
562
+ exit 0
563
+ }
564
+
565
+ deploy "$@"
566
+ ```
567
+
568
+ ### Error handling
569
+
570
+ ```bash
571
+ #!/bin/bash
572
+ set -euo pipefail
573
+
574
+ # Trap para cleanup
575
+ cleanup() {
576
+ local exit_code=$?
577
+ echo "Cleaning up..."
578
+ rm -f /tmp/deploy.lock
579
+ exit $exit_code
580
+ }
581
+ trap cleanup EXIT
582
+
583
+ # Trap para errores
584
+ on_error() {
585
+ echo "Error on line $1" >&2
586
+ }
587
+ trap 'on_error $LINENO' ERR
588
+
589
+ # Verificar dependencias
590
+ check_dependencies() {
591
+ local deps=("git" "ruby" "bundle")
592
+ for dep in "${deps[@]}"; do
593
+ if ! command -v "$dep" &> /dev/null; then
594
+ echo "Error: $dep is required but not installed" >&2
595
+ exit 1
596
+ fi
597
+ done
598
+ }
599
+
600
+ # Función con manejo de errores
601
+ safe_deploy() {
602
+ local server=$1
603
+
604
+ echo "Deploying to $server..."
605
+
606
+ if ! ssh "$server" "cd /app && git pull origin main"; then
607
+ echo "Git pull failed" >&2
608
+ return 1
609
+ fi
610
+
611
+ if ! ssh "$server" "cd /app && bundle install"; then
612
+ echo "Bundle install failed" >&2
613
+ return 1
614
+ fi
615
+
616
+ return 0
617
+ }
618
+
619
+ # Main
620
+ main() {
621
+ check_dependencies
622
+
623
+ for server in "${SERVERS[@]}"; do
624
+ if ! safe_deploy "$server"; then
625
+ echo "Deployment to $server failed, aborting" >&2
626
+ exit 1
627
+ fi
628
+ done
629
+
630
+ echo "All deployments successful!"
631
+ }
632
+
633
+ main "$@"
634
+ ```
635
+
636
+ ## Variables de Entorno
637
+
638
+ ### Export y acceso
639
+
640
+ ```bash
641
+ #!/bin/bash
642
+
643
+ # Definir variables de entorno
644
+ export RAILS_ENV="production"
645
+ export DATABASE_URL="postgres://localhost/myapp"
646
+
647
+ # Cargar desde archivo
648
+ set -a # Auto-export
649
+ source .env
650
+ set +a
651
+
652
+ # O manualmente
653
+ while IFS='=' read -r key value; do
654
+ # Ignorar comentarios y líneas vacías
655
+ [[ $key =~ ^#.*$ ]] && continue
656
+ [[ -z "$key" ]] && continue
657
+ export "$key=$value"
658
+ done < .env
659
+
660
+ # Verificar si está definida
661
+ if [[ -v DATABASE_URL ]]; then
662
+ echo "DATABASE_URL is set"
663
+ fi
664
+
665
+ # Unset
666
+ unset TEMP_VAR
667
+ ```
668
+
669
+ ### dotenv
670
+
671
+ ```bash
672
+ # .env
673
+ RAILS_ENV=production
674
+ DATABASE_URL=postgres://localhost/myapp
675
+ SECRET_KEY_BASE=abc123
676
+ REDIS_URL=redis://localhost:6379
677
+
678
+ # .env.local (no commitear)
679
+ AWS_ACCESS_KEY_ID=AKIA...
680
+ AWS_SECRET_ACCESS_KEY=...
681
+
682
+ # .env.example (commitear como template)
683
+ RAILS_ENV=development
684
+ DATABASE_URL=
685
+ SECRET_KEY_BASE=
686
+ ```
687
+
688
+ ```bash
689
+ #!/bin/bash
690
+ # Función para cargar .env
691
+ load_env() {
692
+ local env_file=${1:-.env}
693
+
694
+ if [[ ! -f "$env_file" ]]; then
695
+ echo "Warning: $env_file not found" >&2
696
+ return 1
697
+ fi
698
+
699
+ while IFS='=' read -r key value; do
700
+ # Trim whitespace
701
+ key=$(echo "$key" | xargs)
702
+ value=$(echo "$value" | xargs)
703
+
704
+ # Skip comments and empty lines
705
+ [[ -z "$key" || $key == \#* ]] && continue
706
+
707
+ # Remove quotes from value
708
+ value="${value%\"}"
709
+ value="${value#\"}"
710
+
711
+ export "$key=$value"
712
+ done < "$env_file"
713
+ }
714
+
715
+ load_env ".env"
716
+ load_env ".env.local" 2>/dev/null || true
717
+ ```
718
+
719
+ ## Cron Jobs
720
+
721
+ ### Sintaxis de crontab
722
+
723
+ ```
724
+ # ┌───────────── minuto (0 - 59)
725
+ # │ ┌───────────── hora (0 - 23)
726
+ # │ │ ┌───────────── día del mes (1 - 31)
727
+ # │ │ │ ┌───────────── mes (1 - 12)
728
+ # │ │ │ │ ┌───────────── día de la semana (0 - 6) (Domingo = 0)
729
+ # │ │ │ │ │
730
+ # * * * * * comando
731
+ ```
732
+
733
+ ### Ejemplos comunes
734
+
735
+ ```bash
736
+ # crontab -e
737
+
738
+ # Cada minuto
739
+ * * * * * /app/scripts/check_health.sh
740
+
741
+ # Cada 5 minutos
742
+ */5 * * * * /app/scripts/sync_data.sh
743
+
744
+ # Cada hora
745
+ 0 * * * * /app/scripts/hourly_task.sh
746
+
747
+ # Diario a las 2:00 AM
748
+ 0 2 * * * /app/scripts/daily_backup.sh
749
+
750
+ # Lunes a las 9:00 AM
751
+ 0 9 * * 1 /app/scripts/weekly_report.sh
752
+
753
+ # Primer día del mes
754
+ 0 0 1 * * /app/scripts/monthly_cleanup.sh
755
+
756
+ # Múltiples horarios
757
+ 0 8,12,18 * * * /app/scripts/three_times_daily.sh
758
+
759
+ # Rango
760
+ 0 9-17 * * 1-5 /app/scripts/business_hours.sh
761
+ ```
762
+
763
+ ### Whenever gem (Ruby)
764
+
765
+ ```ruby
766
+ # Gemfile
767
+ gem "whenever", require: false
768
+
769
+ # config/schedule.rb
770
+ set :output, "log/cron.log"
771
+ set :environment, "production"
772
+
773
+ # Cada día a las 2am
774
+ every 1.day, at: "2:00 am" do
775
+ rake "db:backup"
776
+ end
777
+
778
+ # Cada hora
779
+ every 1.hour do
780
+ runner "DataSync.perform"
781
+ end
782
+
783
+ # Cada 5 minutos
784
+ every 5.minutes do
785
+ rake "health:check"
786
+ end
787
+
788
+ # Solo en producción
789
+ if environment == "production"
790
+ every 1.day, at: "4:00 am" do
791
+ rake "cleanup:old_sessions"
792
+ end
793
+ end
794
+ ```
795
+
796
+ ```bash
797
+ # Generar crontab
798
+ bundle exec whenever
799
+
800
+ # Instalar en crontab
801
+ bundle exec whenever --update-crontab myapp
802
+
803
+ # Eliminar de crontab
804
+ bundle exec whenever --clear-crontab myapp
805
+ ```
806
+
807
+ ## Aliases y Funciones (.bashrc/.zshrc)
808
+
809
+ ```bash
810
+ # ~/.bashrc o ~/.zshrc
811
+
812
+ # Aliases para Rails
813
+ alias be="bundle exec"
814
+ alias rs="bundle exec rails server"
815
+ alias rc="bundle exec rails console"
816
+ alias rr="bundle exec rails routes"
817
+ alias rdbm="bundle exec rails db:migrate"
818
+ alias rdbr="bundle exec rails db:rollback"
819
+ alias rdbs="bundle exec rails db:seed"
820
+ alias rspec="bundle exec rspec"
821
+
822
+ # Alias para Git
823
+ alias gs="git status"
824
+ alias gd="git diff"
825
+ alias gc="git commit"
826
+ alias gp="git push"
827
+ alias gl="git pull"
828
+ alias gco="git checkout"
829
+ alias gb="git branch"
830
+ alias glog="git log --oneline --graph --decorate -20"
831
+
832
+ # Funciones útiles
833
+ # Crear y cambiar a directorio
834
+ mkcd() {
835
+ mkdir -p "$1" && cd "$1"
836
+ }
837
+
838
+ # Buscar en archivos Ruby
839
+ rgr() {
840
+ grep -rn "$1" --include="*.rb" .
841
+ }
842
+
843
+ # Rails: reset database
844
+ dbreset() {
845
+ bundle exec rails db:drop db:create db:migrate db:seed
846
+ }
847
+
848
+ # Git: crear branch y pushear
849
+ gcb() {
850
+ git checkout -b "$1" && git push -u origin "$1"
851
+ }
852
+
853
+ # Docker: entrar a contenedor
854
+ dexec() {
855
+ docker exec -it "$1" /bin/bash
856
+ }
857
+
858
+ # Logs de Rails en tiempo real
859
+ railslogs() {
860
+ tail -f log/"${RAILS_ENV:-development}".log
861
+ }
862
+
863
+ # Matar proceso en puerto
864
+ killport() {
865
+ lsof -ti:"$1" | xargs kill -9
866
+ }
867
+ ```
868
+
869
+ ## Scripts Útiles para Rails
870
+
871
+ ### Deploy script
872
+
873
+ ```bash
874
+ #!/bin/bash
875
+ # scripts/deploy.sh
876
+
877
+ set -euo pipefail
878
+
879
+ APP_DIR="/var/www/myapp"
880
+ BRANCH="${1:-main}"
881
+ RAILS_ENV="${RAILS_ENV:-production}"
882
+
883
+ echo "=== Deploying $BRANCH to $RAILS_ENV ==="
884
+
885
+ cd "$APP_DIR"
886
+
887
+ echo "-> Pulling latest code..."
888
+ git fetch origin
889
+ git checkout "$BRANCH"
890
+ git pull origin "$BRANCH"
891
+
892
+ echo "-> Installing dependencies..."
893
+ bundle install --deployment --without development test
894
+
895
+ echo "-> Compiling assets..."
896
+ RAILS_ENV=$RAILS_ENV bundle exec rails assets:precompile
897
+
898
+ echo "-> Running migrations..."
899
+ RAILS_ENV=$RAILS_ENV bundle exec rails db:migrate
900
+
901
+ echo "-> Restarting application..."
902
+ sudo systemctl restart myapp
903
+
904
+ echo "-> Warming up..."
905
+ sleep 5
906
+ curl -s http://localhost:3000/health || exit 1
907
+
908
+ echo "=== Deployment complete! ==="
909
+ ```
910
+
911
+ ### Backup script
912
+
913
+ ```bash
914
+ #!/bin/bash
915
+ # scripts/backup.sh
916
+
917
+ set -euo pipefail
918
+
919
+ # Configuration
920
+ BACKUP_DIR="/backups"
921
+ DB_PATH="/app/storage/production.sqlite3"
922
+ RETENTION_DAYS=30
923
+ TIMESTAMP=$(date +%Y%m%d_%H%M%S)
924
+
925
+ echo "=== Starting backup ==="
926
+
927
+ # Create backup directory
928
+ mkdir -p "$BACKUP_DIR"
929
+
930
+ # Database backup
931
+ echo "-> Backing up database..."
932
+ cp "$DB_PATH" "$BACKUP_DIR/db_$TIMESTAMP.sqlite3"
933
+
934
+ # Compress
935
+ gzip "$BACKUP_DIR/db_$TIMESTAMP.sqlite3"
936
+
937
+ # Upload backup
938
+ echo "-> Uploading to S3..."
939
+ aws s3 cp "$BACKUP_DIR/db_$TIMESTAMP.sqlite3.gz" \
940
+ "s3://myapp-backups/database/"
941
+
942
+ # Cleanup old backups
943
+ echo "-> Cleaning old backups..."
944
+ find "$BACKUP_DIR" -name "*.gz" -mtime +$RETENTION_DAYS -delete
945
+
946
+ echo "=== Backup complete: db_$TIMESTAMP.sqlite3.gz ==="
947
+ ```
948
+
949
+ ### Migrate script
950
+
951
+ ```bash
952
+ #!/bin/bash
953
+ # scripts/migrate.sh
954
+
955
+ set -euo pipefail
956
+
957
+ RAILS_ENV="${RAILS_ENV:-production}"
958
+
959
+ echo "=== Running migrations for $RAILS_ENV ==="
960
+
961
+ # Check pending migrations
962
+ PENDING=$(RAILS_ENV=$RAILS_ENV bundle exec rails db:migrate:status | grep "down" | wc -l)
963
+
964
+ if [[ $PENDING -eq 0 ]]; then
965
+ echo "No pending migrations"
966
+ exit 0
967
+ fi
968
+
969
+ echo "Found $PENDING pending migrations"
970
+
971
+ # Backup before migration
972
+ echo "-> Creating backup..."
973
+ cp storage/production.sqlite3 "storage/pre_migration_$(date +%Y%m%d_%H%M%S).sqlite3"
974
+
975
+ # Run migrations
976
+ echo "-> Running migrations..."
977
+ RAILS_ENV=$RAILS_ENV bundle exec rails db:migrate
978
+
979
+ # Verify
980
+ echo "-> Verifying..."
981
+ REMAINING=$(RAILS_ENV=$RAILS_ENV bundle exec rails db:migrate:status | grep "down" | wc -l)
982
+
983
+ if [[ $REMAINING -gt 0 ]]; then
984
+ echo "ERROR: $REMAINING migrations still pending!"
985
+ exit 1
986
+ fi
987
+
988
+ echo "=== Migrations complete ==="
989
+ ```
990
+
991
+ ### Health check script
992
+
993
+ ```bash
994
+ #!/bin/bash
995
+ # scripts/health_check.sh
996
+
997
+ set -euo pipefail
998
+
999
+ URL="${1:-http://localhost:3000/up}"
1000
+ TIMEOUT=10
1001
+ RETRIES=3
1002
+
1003
+ check_health() {
1004
+ curl -sf --max-time $TIMEOUT "$URL" > /dev/null
1005
+ }
1006
+
1007
+ for i in $(seq 1 $RETRIES); do
1008
+ if check_health; then
1009
+ echo "Health check passed"
1010
+ exit 0
1011
+ fi
1012
+ echo "Attempt $i failed, retrying..."
1013
+ sleep 2
1014
+ done
1015
+
1016
+ echo "Health check failed after $RETRIES attempts"
1017
+ exit 1
1018
+ ```
1019
+
1020
+ ### Console wrapper
1021
+
1022
+ ```bash
1023
+ #!/bin/bash
1024
+ # scripts/console.sh
1025
+
1026
+ set -euo pipefail
1027
+
1028
+ RAILS_ENV="${1:-production}"
1029
+
1030
+ echo "Opening Rails console for $RAILS_ENV"
1031
+ echo "Type 'exit' to quit"
1032
+ echo ""
1033
+
1034
+ if [[ $RAILS_ENV == "production" ]]; then
1035
+ echo "WARNING: You are in PRODUCTION console!"
1036
+ echo "Be careful with data modifications."
1037
+ echo ""
1038
+ read -p "Are you sure? (yes/no): " confirm
1039
+ [[ $confirm != "yes" ]] && exit 1
1040
+ fi
1041
+
1042
+ RAILS_ENV=$RAILS_ENV bundle exec rails console
1043
+ ```
1044
+
1045
+ ## Template de Script
1046
+
1047
+ ```bash
1048
+ #!/bin/bash
1049
+ #
1050
+ # Script: script_name.sh
1051
+ # Description: Brief description
1052
+ # Usage: ./script_name.sh [options] <arguments>
1053
+ #
1054
+
1055
+ set -euo pipefail
1056
+
1057
+ # ==============================================================================
1058
+ # Configuration
1059
+ # ==============================================================================
1060
+ readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
1061
+ readonly SCRIPT_NAME="$(basename "$0")"
1062
+
1063
+ # ==============================================================================
1064
+ # Functions
1065
+ # ==============================================================================
1066
+ usage() {
1067
+ cat <<EOF
1068
+ Usage: $SCRIPT_NAME [options] <argument>
1069
+
1070
+ Options:
1071
+ -h, --help Show this help message
1072
+ -v, --verbose Enable verbose output
1073
+ -e, --env Environment (default: development)
1074
+
1075
+ Examples:
1076
+ $SCRIPT_NAME -e production
1077
+ $SCRIPT_NAME --verbose
1078
+
1079
+ EOF
1080
+ }
1081
+
1082
+ log() {
1083
+ echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
1084
+ }
1085
+
1086
+ error() {
1087
+ echo "[ERROR] $*" >&2
1088
+ }
1089
+
1090
+ cleanup() {
1091
+ # Cleanup tasks
1092
+ :
1093
+ }
1094
+
1095
+ # ==============================================================================
1096
+ # Main
1097
+ # ==============================================================================
1098
+ main() {
1099
+ local verbose=false
1100
+ local env="development"
1101
+
1102
+ # Parse arguments
1103
+ while [[ $# -gt 0 ]]; do
1104
+ case "$1" in
1105
+ -h|--help)
1106
+ usage
1107
+ exit 0
1108
+ ;;
1109
+ -v|--verbose)
1110
+ verbose=true
1111
+ shift
1112
+ ;;
1113
+ -e|--env)
1114
+ env="$2"
1115
+ shift 2
1116
+ ;;
1117
+ *)
1118
+ error "Unknown option: $1"
1119
+ usage
1120
+ exit 1
1121
+ ;;
1122
+ esac
1123
+ done
1124
+
1125
+ trap cleanup EXIT
1126
+
1127
+ # Script logic here
1128
+ log "Starting script with env=$env verbose=$verbose"
1129
+ }
1130
+
1131
+ main "$@"
1132
+ ```