Revertir automáticamente las confirmaciones que fallan en la compilación

39

Un colega mío me dijo que está pensando en hacer que nuestro servidor de CI revierta las confirmaciones que fallaron en la compilación, por lo que el HEAD en master siempre es estable (como al pasar la compilación al menos).

¿Es esta una buena práctica o puede ser más problemático que simplemente dejar master roto hasta que el desarrollador lo arregle?

Mi idea es que revertir la confirmación hará más compleja la tarea de leer la confirmación y la corrección (el desarrollador tendrá que revertir la reversión y luego la corrección, que también saturará el git log ) y deberíamos dejarlo El cometer y luego cometer el arreglo. Aunque veo algunas ventajas en tener master estable, esta reversión de fallos no me convence.

editar: no importa si es master o cualquier otra rama de desarrollo, pero la pregunta sigue siendo la misma: ¿debe el sistema de CI revertir una confirmación que falló en la compilación?

otra edición (de longitud): Ok, estamos usando git de una manera extraña. Creemos que el concepto de sucursales va en contra del CI real, ya que comprometerse con una sucursal lo aísla de los otros desarrolladores y sus cambios, y agrega tiempo cuando tiene que reintegrar su sucursal y lidiar con posibles conflictos. Si todos se comprometen a master , estos conflictos se reducen al mínimo y cada confirmación pasa todas las pruebas.

Por supuesto, esto te obliga a presionar solo la estabilidad (o romper la compilación) y a programar más cuidadosamente para no romper la compatibilidad hacia atrás o hacer cambios de características al introducir nuevas características.

Hay compensaciones al hacer CI de una o de otra manera, pero eso está fuera del alcance de la pregunta (consulte pregunta relacionada para esto). Si lo prefiere, puedo reformular la pregunta: un pequeño equipo de desarrolladores trabaja en conjunto en una rama de características. Si un desarrollador confirma algo que rompe la compilación de esa rama, ¿debería el sistema de CI revertir el compromiso o no?

    
pregunta Carlos Campderrós 21.08.2015 - 10:03

8 respuestas

52

Estaría en contra de hacer esto por las siguientes razones:

  • Cada vez que configura una herramienta automatizada para cambiar el código en su nombre , existe el riesgo de que no funcione correctamente o de que surja una situación en la que la necesite. deje de hacer ese cambio (por ejemplo, la última versión de Google Mock tenía un error, por lo que no es un error de su código) y tiene que perder tiempo reconfigurándolo. Además, siempre existe un ligero riesgo de que la compilación falle debido a un error en el sistema de compilación, en lugar de un error en su código. Para mí, CI se trata de ganar confianza en que mi código es correcto; esto simplemente lo convertiría en otra fuente de problemas potenciales para que me preocupe.

  • Los tipos de errores que rompen "la compilación" deben ser errores tontos que requieren muy poco tiempo para solucionarlos (como ha indicado en un comentario, esto es cierto para usted) . Si los errores más sutiles y complicados lo hacen regularmente en el maestro, entonces la solución correcta no es "arreglarlo más rápido", sino que debe ser más cuidadoso al revisar las ramas de características antes de que se combinen.

  • Dejar el maestro sin edificar durante unos minutos mientras el error se soluciona correctamente no hace daño a nadie. No es como si el CEO revisara personalmente a Master y publicara el código directamente a los clientes en cualquier momento aleatorio (al menos, con suerte no sin su participación). En el improbable caso de que necesite liberar algo antes de poder solucionar el error, luego puede tomar la decisión de revertir manualmente antes de publicar.

respondido por el Ixrec 21.08.2015 - 13:03
26

Primero acordemos los términos.

Personalmente uso los términos Continuous Build e Continuous Integration para distinguir dos escenarios diferentes:

  • Compilación continua: una herramienta que verifica periódicamente si el repositorio ha cambiado desde la última compilación, y compilación / prueba si lo hizo.
  • Integración continua: una herramienta que toma Solicitudes de extracción y las valida con el último encabezado anterior para hacerlas visibles.

La última, Integración continua, significa que el repositorio que protege es siempre verde 1 : es estrictamente mejor.

Tu pregunta solo tiene sentido para la compilación continua, así que responderé suponiendo que esta es tu configuración.

1 : las causas ambientales también pueden arruinar una compilación, por ejemplo, una prueba con un año de código rígido (2015) puede comenzar a fallar en enero de 2016, un disco puede llenarse, .. Y, por supuesto, está la plaga de pruebas inestables. Aquí descaradamente, ignoro esas cuestiones; de lo contrario nunca llegaremos a ninguna parte.

Si tiene una configuración de compilación continua, puede automatizar la inversión de confirmaciones que pueden haber roto la compilación, sin embargo, hay varias sutilezas.

  • En realidad, no puede eliminar los compromisos: otros compañeros de trabajo ya los han verificado y los rechazarán la próxima vez que intenten comprometerse. En su lugar, una reversión debería estar cometiendo un reverse diff. Ah, y los compañeros de trabajo te odiarán por revertir su trabajo cuando sea correcto, ya que tendrán que encontrar la manera de rechazarlo de nuevo ...
  • En realidad, no solo puede eliminar el último compromiso (es una combinación), sino que debe eliminar todos los compromisos ... hasta cierto punto. Por ejemplo, el último compromiso bueno conocido (tenga cuidado al arrancar el sistema).
  • Debe pensar en causas externas (problemas medioambientales) y evitar una configuración que revierta todo hasta el día 0. Afortunadamente, volver al último compromiso conocido evita este problema.
  • Debe pensar que la última buena compilación conocida ya no se puede construir (problemas del entorno), en cuyo caso es probable que todas las confirmaciones posteriores se inviertan. Lo ideal sería que, en caso de fallo y antes de revertir, compruebe la última versión correcta conocida y la vuelva a probar. Si pasa, revertir, de lo contrario, genera una alerta.

Tenga en cuenta que con este sistema, en el caso de una prueba inestable o de un compañero de trabajo que a menudo comete errores, muchas buenas confirmaciones se revertirán. Tus compañeros te odiarán.

Espero que mi historia de horror haya expuesto los problemas de permitir un repositorio roto y ahora implementará un proceso adecuado de integración continua en el que las PR nunca se envían directamente al repositorio, sino que se ponen en cola para fusionarse en una cola de trabajo y se integran en una vez (o por roll-ups):

  • buscar localmente el jefe del repositorio
  • aplicar solicitud (s) de extracción
  • construir y probar
  • en caso de éxito, empujar al repositorio, de lo contrario marcar como falla
  • pasar a las próximas solicitudes

Habiendo intentado ambos, esto es estrictamente mejor.

    
respondido por el Matthieu M. 21.08.2015 - 15:51
5
  

¿Es esta una buena práctica o puede ser más problemático que simplemente dejar el maestro roto hasta que el desarrollador lo arregle?

Es problemático. Una persona que decide que "el HEAD maestro está roto; revertiré el cambio superior" es completamente diferente al sistema CI que hace lo mismo.

Aquí hay algunas desventajas:

  • Los errores en el proceso de reversión automatizada arruinarán el repositorio;

  • esto supone que un solo conjunto de cambios (el más alto) arruinó la compilación (que no es realista)

  • Los mantenedores tendrán más trabajo que hacer para solucionar el problema, que solo la investigación y el compromiso (también tendrán que mirar el historial inverso)

  

Creemos que el concepto de sucursales va en contra del CI real, ya que comprometerse con una sucursal lo aísla de los otros desarrolladores y sus cambios, y agrega tiempo cuando tiene que reintegrar su sucursal y lidiar con posibles conflictos.

Esta creencia (ramas vs. IC) es incorrecta. Considere mantener una rama estable en una , en la que solo confirma los conjuntos de cambios de unidad probada . El resto (sucursales de características y sucursales locales) debe ser responsabilidad de cada desarrollador y no formar parte de su política de CI de ninguna manera.

En las ramas de características, desea estar aislado de otros desarrolladores. Esto te permite:

  • realizar codificación exploratoria

  • experimenta con el código base

  • realice confirmaciones parciales (confirme efectivamente el código que no funciona) para configurar los puntos de respaldo (en caso de que falle), para crear un historial de cambios más significativo (a través de los mensajes de confirmación), y para respaldar su trabajo y cambiar completamente a otra cosa (en el tiempo que le lleva escribir "git commit & & git checkout")

  • realiza tareas de baja prioridad que llevan mucho tiempo (por ejemplo, quieres realizar una refactorización que altera las 80 clases de la capa de datos: cambias dos por día, hasta que las cambias todas y el código se compila (pero puede hacer esto sin afectar a nadie hasta que pueda hacer un solo compromiso).

  

Si un desarrollador comete algo que rompe la compilación de esa rama, ¿debería el sistema de CI revertir el compromiso o no?

No debería. El hecho de cometer un código estable en su sucursal de CI es responsabilidad del operador, no de un sistema automatizado.

    
respondido por el utnapistim 21.08.2015 - 13:47
2

Sugeriría usar un entorno Gerrit + Jenkins para mantener su rama maestra siempre en buena forma. Las personas envían su nuevo código a Gerrit, lo que activa un trabajo de Jenkins para extraer ese parche, las compilaciones, las pruebas, etc. Si a otros desarrolladores les gusta tu parche y Jenkins completa su trabajo con éxito, Gerrit combinará ese fragmento de código en tu rama principal.

Es un entorno similar descrito por @ brian-vandenberg

Además de mantener su sucursal en buena forma, también agrega un paso de revisión de código que mejora la calidad del código y el intercambio de conocimientos sobre su software.

[1] Jenkins enlace

[2] Gerrit enlace

    
respondido por el Gustavo Coelho 27.08.2015 - 22:58
1

El CI nunca debe alterar el historial de confirmación del repositorio.

La solución correcta aquí es que no se agreguen confirmaciones a la rama maestra si no se han probado y verificado.

¿Trabajas en ramas de características, ejecutas el CI automáticamente y, si las compilaciones fallan, no las fusiones en el maestro?

Puede tener una compilación adicional que fusione las pruebas si se trata de un problema, ejecutándose en la rama de características y durante la compilación de la combinación maestra / integración / lo que sea en la rama local, luego ejecutando pruebas.

    
respondido por el Daenyth 21.08.2015 - 14:19
1

Usamos Jenkins para nuestro servidor de compilación y el modelo del controlador de acceso para empujar los compromisos, donde el controlador de la combinación es una combinación de Jenkins y activadores de compromiso (que aseguran que los revisores pares hayan hecho su trabajo).

Los compromisos se insertan indirectamente a través de un curl en Jenkins, donde clona el repo maestro y luego extrae los compromisos que se fusionarán. y realiza todas las compilaciones requeridas (para Linux / solaris). Si todas las compilaciones se completan, la confirmación se empuja.

Esto evita muchos, si no todos, los problemas discutidos hasta ahora:

  • alteración de la historia
  • corregir el historial si eres el desarrollador que tiene que arreglar la rotura
  • la inestabilidad (en forma de construcciones rotas) nunca se introduce

También nos permite hacer cumplir directamente otros requisitos, como que las pruebas unitarias se completen con éxito.

    
respondido por el Brian Vandenberg 21.08.2015 - 18:12
0

¿Cuántas veces has recibido ese correo electrónico automático que dice que tu última confirmación ha roto la compilación? ¿Cuántas veces está mal? Pero ahora tienes que ir a verificar si realmente fuiste tú o alguien más que hizo otro compromiso al mismo tiempo. O tal vez fue algo ambiental.

Si el sistema no lo sabe a ciencia cierta, entonces ciertamente no quiero automatizarlo.

    
respondido por el Mohair 21.08.2015 - 17:52
0

La pregunta formulada es defectuosa. Aunque respeto esta declaración

"Creemos que el concepto de sucursales va en contra del CI real, porque comprometerse con una sucursal lo aísla de los otros desarrolladores y sus cambios"

Lo que deberías estar haciendo son estos pasos

  • trabaje sin maestro si lo desea (eso está bien y sigue obteniendo cambios de todos) PERO NO se comprometa a dominar localmente
  • JUSTO ANTES DE que confirme sus cambios en el dominio, cree una rama con submit_XXXXXX
  • haga que su compilación automática recoja todas las ramas de submit_XXX compiladas
  • Opción 1: crear saltos, o combinar saltos ... cambio rechazado y nunca aterriza en el maestro
  • Opción 2: trabajos de compilación, jenkins empuja al maestro y lo actualiza

ENTONCES, lo que hacemos es poner un gancho de git commit para evitar que TODOS se comprometan realmente a dominar. Funciona muy bien ... NO hay compilaciones rotas nunca y NO se pueden revertir las confirmaciones del maestro tampoco.

más tarde, Decano

    
respondido por el Dean Hiller 30.09.2016 - 02:58

Lea otras preguntas en las etiquetas