Antecedentes
Estoy trabajando en un equipo que busca implementar implementaciones de tiempo de inactividad cero. Estamos planeando usar una estrategia de implementación azul / verde para lograr esto. Una de las cosas de las que me estoy dando cuenta al investigar es lo complicado que resulta hacer cambios en la base de datos. ¡Una operación simple como cambiar el nombre de una columna puede tomar 3 ciclos completos de liberación hasta que se complete!
Me parece que tener el despliegue completo de un cambio tomar múltiples ciclos de lanzamiento introduce un gran potencial para el error humano. En el artículo vinculado, muestra que los cambios de código son necesarios para 2 versiones y una migración de base de datos para 3 versiones.
Lo que estoy buscando
Actualmente, si queremos recordar hacer algo, podemos crear un ticket en nuestro sistema de administración de problemas, lo que crea desorden y también puede ser trasladado a un sprint posterior o al retraso de la administración; o podemos crear un comentario TODO, que probablemente se olvidará por completo.
Lo que estoy buscando es una forma en que un comentario TODO pueda tener una fecha límite en su contra, y nuestro sistema de Integración Continua (actual indeciso que usaremos) rechazaría la compilación si esta fecha límite expirara.
Por ejemplo, si cambiamos el nombre de una columna, podríamos crear la migración inicial para ella, y luego dos comentarios TODO para garantizar que se creen las dos migraciones restantes:
// TODO by v55: Create migration to move constraints to new column, remove references to old column in app
// TODO by v56: Create migration to drop old column
Esto parece bastante simple de implementar, pero me pregunto si ya existe algo como esto, porque no quiero reinventar la rueda.
Pensamientos adicionales
Siento que podría estar sufriendo un problema XY aquí, dado que las implementaciones continuas y las implementaciones azul / verde se consideran una práctica recomendada, parece extraño que no pueda encontrar una solución para hacer que las actualizaciones de la base de datos sean menos dolorosas. Si crees que estoy investigando algo completamente incorrecto, ¡házmelo saber en un comentario! Dicho esto, el ejemplo de la base de datos que di es solo un ejemplo, y creo que los comentarios TODO con fechas de vencimiento también serían útiles en otras situaciones, por lo que incluso si me estoy acercando a esta situación específica completamente equivocada, realmente me gustaría responder a mi pregunta real también. ¡Gracias!
EDITAR: Acabo de pensar en otra situación en la que esto podría ser útil. Si usa las funciones de alternancia para activar partes de su aplicación cuando estén listas, debe tener cuidado de limpiarlas, de lo contrario, podría terminar con la deuda de alternancia . Los comentarios con fechas límite podrían ser una buena forma de recordar esto.
fuente
TODO <Bug#>:
para rastrear soluciones a problemas con otros componentes. Cuando se elimina un error en uno de esos componentes, puede encontrar y abordar fácilmente las soluciones alternativas. No reemplaza un rastreador de problemas, lo hace más fácil de mantener.Respuestas:
Esta pregunta es realmente dos preguntas en una.
Todo comentarios
De todas las formas de rastrear elementos de acción, esta es la peor. Los comentarios TODO son buenos durante el trabajo activo o como una forma de sugerencia para un responsable de mantenimiento, "esto es algo que podría mejorarse en el futuro". Pero si confía en los comentarios de TODO para realizar el trabajo, está condenado al fracaso.
Qué hacer al respecto
Los comentarios de TODO son básicamente deudas técnicas, por lo que deben manejarse como cualquier otra deuda técnica. Abórdelos de inmediato, si tiene tiempo, o póngalos en la cartera de pedidos para que puedan rastrearse y priorizarse.
En términos generales, y esto es totalmente obstinado y abierto a debate, TODO los comentarios podrían considerarse un olor a código. Si un comentario de TODO llega al control de la versión, debe preguntarse, ¿realmente lo va a seguir en este momento? Si no, está bien. Solo sé honesto contigo mismo y ponlo en la cartera.
La forma en que gestiona este trabajo atrasado se reduce a procesos comerciales, políticas de la empresa y, tal vez, cierta autonomía personal. Pero aún necesita un registro de seguimiento rastreado y priorizado para asegurarse de que suceda.
Cambios en la base de datos.
Sí, los cambios en la base de datos son complicados con una política de tiempo de inactividad cero. Algunos trucos para ayudar a que sea menos doloroso:
Proceso posterior a la implementación
Cree un proceso posterior a la implementación que se ejecute como parte de la misma versión. Sin embargo, quieres que funcione. En el último sistema en el que trabajé, diseñé una implementación de 4 fases:
La idea era que siempre que fuera posible, pondríamos la mayor cantidad posible de cambios en la base de datos en preapp.
Postapp estaba reservado para los casos inusuales en los que necesitábamos hacer cambios de esquema incompatibles. En esos casos, preapp haría un cambio suficiente para hacer que el nuevo código de aplicación sea compatible (tal vez creando una vista temporal para compatibilidad), y postapp limpiaría dichos artefactos temporales.
La fase de la ventana de mantenimiento estaba reservada para los cambios que realmente requerían tiempo de inactividad o donde el riesgo o el costo de una implementación en vivo no valía la pena. Por ejemplo, los scripts que cambian cantidades masivas de datos pueden necesitar bloquear una tabla completa.
Implementar con frecuencia
Si implementa nuevas versiones con la frecuencia suficiente, puede llegar a un punto en el que llevar un cambio en 2 o 3 versiones es trivial. Los ciclos de lanzamiento largos amplifican el costo de los cambios en la base de datos.
fuente
No use TODOs. Ya tienes una lista TODO en tu proyecto. Se llama el rastreador de problemas.
Creo que el verdadero problema está en esta oración:
Si su rastreador de problemas crea demasiado desorden, busque formas de solucionarlo. Tal vez un tipo / etiqueta de problema especial que implica menos ceremonia. Quizás subtemas. Quizás menos ceremonia por completo. Realmente no podemos decirlo. Pero si su rastreador de problemas crea tanto trabajo, que las personas prefieren formular una pregunta elaborada en un foro público que simplemente agregar ese problema, algo está muy mal.
Si su administración retrasa indebidamente la última parte de una tarea, tiene dos opciones:
Hable con su gerencia por qué es una mala idea.
manejarlo como una sola tarea. Esta podría ser la solución estándar de oro. En un mundo perfecto, deberías poder hacer los tres cambios necesarios en cada paso. Aplique uno a la rama maestra, déjelo construir e implementar. Mientras tanto, aplique el segundo a la rama maestra, déjelo construir y desplegar, y así sucesivamente para que todo suceda en el mismo sprint, y si no lo hace, no se hace. Tal vez incluso algo automático tiene sentido cuando lógicamente haces una implementación, pero en realidad se divide en 3.
fuente
// TODO(#12345): Frobnicate the sprocket before passing it along
, siempre que el error # 12345 sea un número de problema "real" y el problema se asigne a alguien. Esto hace que la fuente sea más fácil de leer al aclarar: "No, el paso de frobnicate no se esconde en uno de los métodos auxiliares, simplemente no está implementado. Ve al bug # 12345 para obtener más contexto". Idealmente, debería tener una interfaz diaria que se ejecute sobre la base de código en busca de números de problema cerrados o no válidos, por supuesto.Lo que pides es factible si estás dispuesto a hacer el trabajo y seguir adelante.
grep para
//TODO by v55
cuando es hora de implementar v55. Deploy build ejecuta un script que lo hace como prueba de integración.Puede vincular 55 en el seguimiento de su versión o simplemente solicitarlo.
Se vuelve interesante si desea verificar // TODO por v54 cuando hace 55. En lugar de buscar la base de código 55 veces, simplemente busque // TODO por. Luego filtre ese resultado de 1 a 55. Ahora 56 no activará una falla.
Puede pensar "oh, no necesitaremos eso. Solucionaremos esto siempre que tengamos el cheque". No. No, no lo harás.
fuente
Tuvimos un problema muy similar en nuestro equipo. Para resolver esto, escribimos una verificación de análisis estático que maneja estos TODOS verificando el problema JIRA o el Problema Git al que hacen referencia. Nuestra compilación falla cuando el problema especificado pasa de la columna "En desarrollo".
Por lo tanto, podemos tener TODO cómodamente sin preocuparnos de que se olviden.
Creé una implementación de código abierto de esto, en Java. Sí, un descargo de responsabilidad es que escribí esto, pero como dije es de código abierto y con licencia.
La herramienta se llama Westie y un ejemplo del verificador de problemas de Jira está en README.md. Vea también el GitIssueAnalyser.
Para evitar la promoción personal si tiene más preguntas, envíeme un mensaje. Si decide usarlo y tiene alguna sugerencia, plantee cualquier problema en github.
fuente
No hacer Hazlo ahora.
TLDR: escriba (y pruebe) sus scripts de base de datos ahora, no más tarde; simplemente codifíquelos para que su ejecución dependa de la versión DB.
Ejemplo
Por ejemplo, imaginemos que desea cambiar el nombre de una columna de
SSN
aTaxID
, un requisito común cuando se internacionaliza.Para que esto suceda, tal vez tenga temporalmente una
TaxID
y unaSSN
columna. Y si bien admite ambas versiones, tendrá un activador para actualizar una desde la otra. Pero no desea mantener ese desencadenador indefinidamente, por lo que más tarde, cuando ya no sea necesaria la compatibilidad con versiones anteriores, desea que se elimine ese desencadenante (y se elimine laSSN
columna). Vamos a codificar todo eso por adelantado sin necesidad de elementos de tareas pendientes.En nuestro ejemplo, implementaremos la compilación 102 (que tiene la nueva columna) mientras mantenemos la compatibilidad con la compilación 101 (que no).
Aquí están los pasos.
1. Configurar tabla de versiones
Agregue una sola tabla llamada
Configuration
con dos columnas,Name
yValue
.Agregue una fila con un
Name
"TargetVersion" y establezcaValue
la versión de la nueva compilación que se implementará.Agregue una fila con un
Name
"CompatibleWith" y establezca elValue
número de versión mínimo con el que la implementación debe ser compatible.Inspeccione y actualice estas filas antes de cada implementación.
2. Modificar scripts de implementación
Agregue una secuencia de comandos que cree una nueva columna de
TaxID
, lado a ladoSSN
, y la complete desde laSSN
columna. Incluya este código en unaIf
declaración que verifique TargetVersion; si la versión de destino es demasiado baja (es decir,TaxID
todavía no es necesaria), omita.Agregue un script que cree un desencadenador que se complete
TaxID
al insertar o actualizarSSN
y viceversa. Incluya este código en unaIf
declaración que verifique la versión de destino y la versión compatible; omita si TargetVersion es demasiado bajo (TaxID
no es necesario) o si la versión CompatibleWith es demasiado alta (elSSN
campo no es necesario).Agregue un script para eliminar la
SSN
columna. Adjunte unaIf
declaración que elimine la columna solo si la versión CompatibleWith es lo suficientemente alta (SSN
ya no es necesaria).3. Prueba
Asegúrese de probar su implementación con cualquier combinación de números de versión Azul / Verde que desee admitir en producción. Puede probar tan pronto como el código esté listo, manipulando la
Configuration
tabla en su entorno de control de calidad.4. En su libro de jugadas de implementación
Agregue un paso para que un ingeniero actualice la versión CompatibleWith y las filas TargetVersion. Si está implementando en Blue, configure TargetVersion en el número de versión de Blue y la versión CompatibleWith en el número de versión de Green; inviértelas si estás desplegando Green.
Trampas
Está bien que sus scripts de implementación hagan referencia y confíen en los números de versión contenidos en esa tabla de base de datos. NO código de tiempo de ejecución.
Si comienza a escribir su código de tiempo de ejecución para inspeccionar los números de versión, está introduciendo un nuevo nivel de complejidad en su aplicación que podría convertirse en un gran problema de mantenimiento. Cada ruta de ejecución de tiempo de ejecución debe ser probada; Si llevas estas condiciones en el futuro, el control de calidad tendrá que armar una matriz de dolor para validarlas con cada lanzamiento. Mi consejo es mantener condiciones como estas solo en los scripts de implementación.
El resultado de todo esto
Al final, deberías poder escribir todo el código por adelantado (y probarlo también) sin temor a que se ejecute demasiado pronto. Además, el código limpiará el activador de compatibilidad con versiones anteriores cuando llegue el momento sin que tenga que preocuparse más por ello.
De esta manera, puede escribir y probar todo el código por adelantado, cuando lo esté pensando, y no necesita lidiar con esos comentarios desordenados de tareas pendientes.
fuente
Usted está recibiendo muchos rechazos en su idea TODO, pero personalmente no veo ningún problema con eso. Al final, la mejor (y más fácil) manera de asegurarse de que la migración entre en producción es fallando una prueba unitaria si no es así. Literalmente, le llevará menos de un minuto desactivar una función de migración vacía que arroje una excepción si la versión es 55 o más (o cualesquiera que sean los requisitos).
Luego, si intenta liberarlo, terminará con una prueba fallida, y alguien tendrá que convertir esa excepción en un código de migración real.
fuente
Nadie parece centrarse en la raíz de su queja, que es el hecho de que los cambios en la base de datos pueden tomar demasiados ciclos de lanzamiento. Quiere continuar con su programa de implementación azul / verde y la solución ya debería estar allí, pero a menos que me falte algo, su descripción parece indicar que solo hay una base de datos compartida por ambos sistemas. No es un verdadero sistema azul / verde si ese es el caso. Dado que parece que la base de datos es el polo largo de la tienda, también debe duplicarse para que, sin importar cuánto tiempo o cuántos ciclos de lanzamiento se necesiten para implementar los cambios de la base de datos en el sistema fuera de línea, no se activen hasta que se completen y Totalmente probado. En el sistema sin conexión provisional, los scripts pueden mantener la base de datos sin conexión totalmente actualizada diariamente.
fuente