
Checklist de entrega de proyecto de software: una salida limpia
La mayoría de los equipos piensa en el checklist de entrega de proyecto de software en el peor momento: la semana en que termina la relación con un proveedor, se va un contratista o una adquisición pregunta quién es dueño de qué. Para entonces, los problemas caros ya están incorporados: producción corriendo en una cuenta de nube a la que nadie de tu lado puede entrar, un deploy que solo funciona desde la laptop de una persona, secretos subidos al repositorio hace tres años. Este artículo trata la entrega como un problema de ingeniería que se diseña desde el primer commit, para que cualquier equipo competente pueda hacerse cargo del sistema mañana. Si todavía estás eligiendo proveedor, empieza por nuestra guía sobre cómo elegir una empresa de desarrollo de software; este texto trata del sistema que construyes una vez que lo tienes.
Por qué la entrega es un problema de arquitectura, no de papeleo
Un documento de entrega escrito al final de un proyecto describe el sistema como alguien lo recuerda. Una entrega integrada en el repositorio describe el sistema como realmente corre, porque el CI lo verifica cada semana. La diferencia aparece en cuatro lugares:
- Propiedad: quién tiene las credenciales raíz del código, la nube, el DNS, las tiendas de apps y los procesadores de pago.
- Reproducibilidad: si un ingeniero nuevo puede pasar de clonar a correr pruebas y desplegar en staging usando solo lo que está en el repo.
- Estado: si la infraestructura y los datos se pueden reconstruir o restaurar sin conocimiento tribal.
- Razonamiento: si el siguiente equipo sabe por qué las cosas son como son, para no deshacer una decisión que se tomó por una buena razón.
Cada uno de estos puntos lo puede verificar una máquina. Esa es la idea central: convertir el checklist en verificaciones.
El checklist de entrega de proyecto de software, capa por capa
1. Propiedad: organizaciones, no personas
Cada activo debe pertenecer a una cuenta de organización que controla el cliente, con el proveedor invitado como miembro con acceso acotado y revocable. El antipatrón común es el contrario: el proveedor crea el repositorio, la cuenta de nube o la ficha en la tienda de apps bajo su propia cuenta y promete transferirla después.
Las transferencias son posibles, pero tienen efectos secundarios que conviene conocer antes de depender de ellas. Según la documentación de GitHub sobre transferir un repositorio, mover un repositorio privado a un usuario u organización con GitHub Free hace que pierda funciones como ramas protegidas y GitHub Pages, y en algunos casos GitHub retira de forma permanente la combinación anterior de dueño/nombre. Las cuentas de nube, las fichas de apps móviles y las cuentas de procesadores de pago tienen cada una sus propios procedimientos de transferencia, normalmente más lentos. Crearlas con el dueño correcto desde el primer día es más barato que cualquier migración.
Haz la propiedad explícita y revisable con un manifiesto en la raíz del repositorio:
# ownership.yaml - se revisa en cada release
assets:
- name: source code
system: GitHub organization acme-co
owner: client
admins: [cto@acme.example, ops@acme.example]
- name: production cloud
system: cloud account (prod)
owner: client
billing: client
vendor_access: scoped role, time-boxed
- name: domain and DNS
system: registrar + DNS provider
owner: client
renewal: auto, client billing
- name: payments
system: payment processor account
owner: client
vendor_access: restricted API key
La regla práctica: al menos dos personas del lado del cliente son administradoras en cada línea, y ninguna línea tiene como único administrador un correo personal del proveedor.
2. Builds reproducibles: un punto de entrada por tarea
Si la configuración requiere una página de wiki con quince pasos manuales, esos pasos se alejarán de la realidad. Un patrón simple y duradero es un conjunto fijo de scripts que todo proyecto expone, popularizado por la convención Scripts to Rule Them All de GitHub:
script/bootstrap # instala toolchain y dependencias desde los lockfiles
script/setup # crea la base local y carga datos semilla anonimizados
script/test # corre toda la suite de pruebas
script/server # levanta la app en local
script/deploy # despliega a un entorno: script/deploy staging
Combínalo con lockfiles versionados para cada gestor de paquetes, versiones de runtime fijadas (un archivo de versión o una definición de dev container) y un .env.example que liste cada variable que lee la app, con un comentario que explique dónde vive el valor real. La prueba es directa: el CI debe poder correr script/bootstrap y script/test en una máquina limpia. Si el CI puede, un equipo nuevo también.
3. Infraestructura como código y el problema del drift
La infraestructura creada con clics en una consola es lo que con más frecuencia no sobrevive a una entrega. Hay tres opciones realistas, cada una con sus compromisos:
- Infraestructura como código (Terraform, OpenTofu, Pulumi, CloudFormation): todo es revisable y reconstruible, pero exige disciplina y alguien que sepa leerlo.
- Plataformas administradas (PaaS, hosting serverless): mucha menos infraestructura que entregar, pero la configuración sigue viviendo en paneles y aceptas los límites y precios de la plataforma.
- Click-ops documentado: lo más rápido para empezar y lo más difícil de verificar. Aceptable solo para sistemas muy pequeños, con capturas y una exportación de la configuración.
Elijas lo que elijas, el modo de falla es el mismo: alguien cambia producción a mano y el código deja de describir la realidad. Detecta el drift de forma programada. Con Terraform, plan -detailed-exitcode devuelve 0 cuando no hay cambios, 1 si hay error y 2 cuando la infraestructura real difiere del código (ver la documentación de terraform plan):
#!/usr/bin/env bash
# scripts/check-drift.sh
set +e
terraform plan -detailed-exitcode -input=false -lock=false
code=$?
set -e
case $code in
0) echo 'No drift' ;;
2) echo 'Drift: live infrastructure differs from code'; exit 1 ;;
*) echo 'Plan failed'; exit $code ;;
esac
Si heredas recursos creados en consola, ponlos bajo gestión con los import blocks de Terraform antes de la entrega, no después, mientras las personas que los crearon todavía pueden responder preguntas.
4. Secretos: inventariar, escanear, rotar
Asume que cada secreto que vio el equipo saliente está comprometido, en el sentido de que ya no es exclusivamente tuyo. Eso lleva a tres pasos.
Inventario. Mantén una lista de cada secreto, dónde se guarda y cómo se rota. El procedimiento de rotación es la parte que siempre falta:
- key: PAYMENTS_SECRET_KEY
stored_in: secrets manager, path prod/payments
used_by: [api, worker]
rotate: roll key in provider dashboard, update secret, redeploy api and worker
last_rotated: filled in at handover
Escanea todo el historial. Borrar un secreto en un commit posterior no lo elimina del historial de Git. Herramientas como gitleaks escanean cada commit de cada rama; revisa el README para la sintaxis actual de la CLI, porque los subcomandos han cambiado entre versiones:
# escanea todos los commits de todas las ramas, no solo el árbol de trabajo
gitleaks detect --source . --log-opts='--all' --report-path gitleaks.json
Rota. El día de la entrega, rota todo lo que está en el inventario, revoca tokens de acceso, llaves SSH y tokens personales del proveedor, y elimina a sus miembros de las organizaciones. Hazlo en una sola ventana planeada con el equipo nuevo de guardia, porque la rotación es el momento en que se rompen las dependencias ocultas.
5. Datos: migraciones en el repo y restauraciones probadas
Los cambios de esquema pertenecen a migraciones versionadas que se suben junto con el código, nunca aplicadas a mano. Los respaldos solo cuentan si se ha probado una restauración, así que convierte el simulacro en un script:
# restaura el último snapshot en una base desechable y corre pruebas de humo
./scripts/restore-backup.sh --snapshot latest --target handover-drill
DATABASE_URL=$DRILL_URL ./script/test --smoke
Agrega un inventario breve de datos: qué tablas contienen datos personales, qué terceros reciben copias y cuánto tiempo se conservan. El equipo receptor lo necesita para responder solicitudes de clientes y reguladores en su primera semana.
6. Conocimiento: ADRs y runbooks junto al código
Los Architecture Decision Records son archivos Markdown cortos que capturan una decisión cada uno; adr.github.io reúne plantillas y herramientas. Responden la pregunta que más hacen los equipos nuevos: ¿por qué está construido así?
# ADR-007: Generar facturas en una cola de trabajos en segundo plano
Status: accepted
Context: los PDF de facturas tardaban lo suficiente como para bloquear peticiones web a fin de mes.
Decision: encolar la generación; enviar el PDF por correo cuando esté listo.
Consequences: requiere un proceso worker y política de reintentos; las facturas no son instantáneas.
Acompáñalos con un runbook que cubra las operaciones que alguien necesitará a las 2 a. m.: cómo desplegar, revertir, reiniciar workers, rotar una llave, restaurar un respaldo y dónde viven los logs y las alertas. Cada entrada del runbook debe apuntar a un script, no describir un procedimiento manual.
Haz que el checklist sea ejecutable
Las verificaciones de entrega anteriores vale la pena correrlas de forma programada durante toda la vida del proyecto, no una sola vez al final. Un job semanal de CI que se comporta como un desconocido que llega al repo detecta el deterioro a tiempo:
name: handover-check
on:
schedule:
- cron: '0 6 * * 1'
workflow_dispatch:
jobs:
stranger-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- run: script/bootstrap
- run: script/test
- run: scripts/check-drift.sh
- run: scripts/check-docs.sh
# instala gitleaks primero, luego:
- run: gitleaks detect --source . --log-opts='--all'
La verificación de documentación puede ser tan simple como fallar cuando desaparecen archivos obligatorios:
#!/usr/bin/env bash
# scripts/check-docs.sh
for f in README.md ownership.yaml .env.example docs/runbook.md docs/adr; do
[ -e $f ] || { echo missing: $f; exit 1; }
done
La verificación final es humana: antes de que se vaya el equipo saliente, un ingeniero del equipo receptor despliega un cambio pequeño a producción usando solo el repositorio y el runbook, mientras el equipo saliente observa sin tocar el teclado. Cada pregunta que haga es un hueco que hay que corregir en el repo.
Compromisos que conviene decidir temprano
- Librerías y licencias del proveedor. Si el código depende de paquetes privados o frameworks internos del proveedor, la entrega está incompleta. O se entregan con una licencia que te permita seguir usándolos y modificándolos, o se reemplazan. Genera una lista de dependencias con licencias (un SBOM en formato SPDX o CycloneDX sirve) y revísala.
- Monorepo frente a muchos repositorios. Un monorepo es más fácil de entregar como unidad; muchos repositorios necesitan un índice que liste cada uno, su propósito y su destino de despliegue.
- Cuentas de herramientas de observabilidad. Las herramientas de logs, rastreo de errores y monitoreo de disponibilidad suelen darse de alta a nombre del proveedor. Trátalas como cualquier otro activo del manifiesto de propiedad, o perderás tu historial el día de la entrega.
Cuando construimos software a la medida para clientes, preferimos resolver estas decisiones en la primera semana, porque cada una es barata al inicio y costosa al final. Lo mismo aplica a los sitios de marketing: dominios, DNS y cuentas del CMS son los activos que más a menudo quedan en las manos equivocadas, por eso nuestros proyectos de páginas web empiezan con el cliente como dueño de las cuentas del registrador y del hosting.
Errores comunes
- Aceptar un archivo ZIP o un repositorio nuevo sin historial. Pierdes el contexto de cada cambio y cualquier posibilidad de escanear commits antiguos.
- Rotar secretos antes de mapearlos, y luego descubrir un cron job en un servidor olvidado que usaba la llave anterior.
- Dar los respaldos por resueltos porque el proveedor dice que están habilitados, sin haber restaurado nunca uno.
- Escribir el documento de entrega en la última semana, de memoria.
- Quitar el acceso al proveedor antes de que el equipo receptor haya hecho un deploy a producción por su cuenta.
- Olvidar los activos que no son código: cuentas de tiendas de apps, certificados de notificaciones push, dominios de envío de correo, propiedades de analítica.
El checklist
- Cada activo está en
ownership.yamlcon un dueño del lado del cliente y dos administradores. - Los repositorios viven en una organización del cliente con un plan que conserva la protección de ramas.
script/bootstrapyscript/testpasan en un runner de CI limpio.- Las versiones de runtime y las dependencias están fijadas y los lockfiles están versionados.
- La infraestructura está en código y una verificación programada de drift pasa.
- Se escaneó todo el historial de Git en busca de secretos y se resolvieron los hallazgos.
- Existe un inventario de secretos con pasos de rotación, y cada secreto se rota en la entrega.
- Las migraciones de esquema están versionadas y un simulacro de restauración de respaldo pasó.
- Los ADRs cubren las decisiones principales; un runbook cubre deploy, rollback y restauración.
- Se revisó una lista de dependencias y licencias, sin código privado del proveedor sin licencia.
- El equipo receptor desplegó a producción sin ayuda.
- El acceso del proveedor se revoca al final, después de los pasos anteriores.
Preguntas frecuentes
¿Cuándo se debe empezar un checklist de entrega de proyecto de software?
El primer día. La mayoría de los puntos, como la propiedad de cuentas, los lockfiles y la infraestructura como código, casi no cuestan nada al inicio y después se convierten en migraciones. Correr las verificaciones en CI durante todo el proyecto hace que la entrega final sea una comprobación, no un rescate.
¿Es obligatoria la infraestructura como código en un proyecto pequeño?
No siempre. Una app pequeña en una plataforma administrada puede tener poca infraestructura que describir. Lo obligatorio es que cada configuración se pueda encontrar, exportar y reproducir, y que las cuentas pertenezcan al cliente.
¿Qué hacemos si el proveedor ya es dueño de las cuentas?
Primero inventaria todo y luego planea las transferencias un activo a la vez, leyendo la documentación de transferencia de cada proveedor para conocer los efectos secundarios. Rota secretos y revoca accesos solo después de que el equipo receptor confirme que puede desplegar y operar el sistema.


