Estoy trabajando en un gran proyecto de código abierto dirigido por la investigación, con muchos otros colaboradores habituales. Debido a que el proyecto ahora es bastante grande, un consorcio (compuesto por dos empleados a tiempo completo y pocos miembros) se encarga de mantener el proyecto, la integración continua (CI), etc. Simplemente no tienen tiempo para la integración de contribuciones sin embargo.
El proyecto se compone de un marco "central", de aproximadamente medio millón de líneas de código, un montón de "complementos" que mantiene el consorcio y varios complementos externos, la mayoría de los cuales no estamos t incluso consciente de.
Actualmente, nuestro CI crea el núcleo y los complementos mantenidos.
Uno de los grandes problemas que enfrentamos es que la mayoría de los contribuyentes (y especialmente los ocasionales) no están construyendo el 90% de los complementos mantenidos, por lo que cuando proponen cambios de refactorización en el núcleo (que actualmente ocurre de manera bastante regular), comprobaron que el código se compila en su máquina antes de realizar una solicitud de extracción en GitHub.
El código funciona, están contentos, y luego el CI termina de compilarse y comienzan los problemas: la compilación falló en un complemento mantenido por el consorcio, que el contribuyente no construyó en su máquina.
Ese complemento puede tener dependencias de bibliotecas de terceros, como CUDA, por ejemplo, y el usuario no quiere, no sabe cómo, o simplemente no puede, por razones de hardware, compilar ese complemento roto.
De manera que - ya sea el estancias de relaciones públicas ad aeternam en el limbo de la no-a-ser-fusionado RP - O el contribuyente GREPS la variable cuyo nombre cambió en la fuente del plugin roto, cambia el código, empuja a su / su rama, espera el CI para terminar de compilar, generalmente recibe más errores y reitera el proceso hasta que CI esté contento, o uno de los dos permanentes que ya están sobrevendidos en el consorcio echa una mano e intenta arreglar el RP en su máquina.
Ninguna de esas opciones es viable, pero simplemente no sabemos cómo hacerlo de manera diferente. ¿Alguna vez te has enfrentado a una situación similar de tus proyectos? Y si es así, ¿cómo manejó este problema? ¿Hay alguna solución que no esté viendo aquí?
fuente
Respuestas:
¡El desarrollo impulsado por CI está bien! ¡Esto es mucho mejor que no ejecutar pruebas e incluir código roto! Sin embargo, hay un par de cosas para facilitar esto a todos los involucrados:
Establezca expectativas: tenga documentación de contribución que explique que CI a menudo encuentra problemas adicionales, y que estos deberán corregirse antes de una fusión. Quizás explique que los cambios locales pequeños tienen más probabilidades de funcionar bien, por lo que dividir un cambio grande en múltiples RP puede ser sensato.
Fomente las pruebas locales: facilite la configuración de un entorno de prueba para su sistema. ¿Un script que verifica que se hayan instalado todas las dependencias? ¿Un contenedor Docker listo para usar? ¿Una imagen de máquina virtual? ¿Tiene su corredor de pruebas mecanismos que permitan priorizar las pruebas más importantes?
Explicar cómo usar CI para sí mismos: parte de la frustración es que esta retroalimentación solo llega después de enviar un RP. Si los contribuyentes configuran CI para sus propios repositorios, recibirán comentarios anteriores y producirán menos notificaciones de CI para otras personas.
Resuelva todos los RP, de cualquier manera: si algo no se puede fusionar porque está roto, y si no hay progreso para solucionar los problemas, simplemente ciérrelo. Estas relaciones públicas abiertas abandonadas desordenan todo, y cualquier comentario es mejor que simplemente ignorar el problema. Es posible expresar esto muy bien y dejar en claro que, por supuesto, sería feliz fusionarse cuando se solucionen los problemas. (ver también: El arte de cerrar por Jessie Frazelle , Mejores prácticas para mantenedores : aprender a decir que no )
También considere hacer que estos RP abandonados sean reconocibles para que otra persona pueda recogerlos. Esto incluso puede ser una buena tarea para los nuevos contribuyentes, si los problemas restantes son más mecánicos y no necesitan una profunda familiaridad con el sistema.
Para la perspectiva a largo plazo, esos cambios parecen romper funcionalidades no relacionadas que a menudo podrían significar que su diseño actual es un poco problemático. Por ejemplo, ¿las interfaces del complemento encapsulan adecuadamente las partes internas de su núcleo? C ++ facilita la filtración accidental de detalles de implementación, pero también hace posible crear fuertes abstracciones que son muy difíciles de usar mal. No puede cambiar esto durante la noche, pero puede guiar la evolución a largo plazo del software hacia una arquitectura menos frágil.
fuente
La construcción de un modelo de complemento sostenible requiere que su marco principal exponga una interfaz estable en la que los complementos puedan confiar. La regla de oro es que puede introducir nuevas interfaces con el tiempo, pero nunca puede modificar una interfaz ya publicada. Si sigue esta regla, puede refactorizar la implementación del marco central todo lo que desee sin temor a romper accidentalmente los complementos, ya sea uno mantenido por el consorcio o uno externo.
Por lo que describió, parece que no tiene una interfaz bien definida, y eso hace que sea difícil saber si un cambio romperá los complementos. Trabaje para definir esta interfaz y hacerla explícita en su base de código, para que los contribuyentes sepan lo que no deben modificar.
fuente
Para ser honesto, no creo que pueda manejar esto de una mejor manera: si los cambios resultan en la ruptura de partes mantenidas de su proyecto, el CI debería fallar.
¿Tiene su proyecto
contributing.md
algo o algo similar para ayudar a los contribuyentes nuevos y ocasionales a preparar sus contribuciones? ¿Tiene una lista clara, qué complementos son parte del núcleo y deben seguir siendo compatibles?Si es difícil construir todo en una máquina debido a dependencias, etc., podría pensar en crear imágenes de acoplador listas para usar como entornos de compilación para que las utilicen sus colaboradores.
fuente
Así que creo que aquí es donde puede caer el estilo suelto de los proyectos de código abierto; La mayoría de los proyectos organizados centralmente desconfían de la refactorización central, especialmente cuando cruza un límite API. Si refactorizan un límite de API, generalmente es un "big bang" donde todos los cambios se programan a la vez con un incremento a la versión principal de API, y se mantiene la API anterior.
Propondría una regla "todos los cambios de API deben planificarse por adelantado": si entra un RP que realiza un cambio incompatible hacia atrás en la API, de alguien que no ha estado en contacto con los mantenedores para acordar su enfoque por adelantado, simplemente se cierra y el remitente señaló la regla.
También necesitará versiones explícitas de la API del complemento. Esto le permite desarrollar v2 mientras todos los complementos v1 continúan construyéndose y funcionando.
También me preguntaría un poco más por qué se están realizando tantos cambios de API y refactorización central. ¿Son realmente necesarios o simplemente personas que imponen su gusto personal en el proyecto?
fuente
Parece que el proceso de CI debe ser más estricto, más completo y más visible para los contribuyentes antes de que generen un PR Como ejemplo, BitBucket tiene una función de canalización que permite esto, donde le da un archivo que define en código el proceso de compilación de CI, y si falla, se evita que la rama se fusione.
Independientemente de la tecnología, proporcionar compilaciones automáticas cuando un contribuyente se dirige a una sucursal les dará una respuesta mucho más rápida sobre lo que deben tener en cuenta al realizar cambios y conducirá a relaciones públicas que no necesitan reparaciones después del hecho.
Sería bueno solucionar los problemas de diseño, pero son ortogonales a este problema.
fuente
Su solución es simple: baje la barrera a la contribución .
La forma más sencilla de (1) acelerar el ciclo de edición-compilación-prueba y (2) las diferencias de entorno sin problemas es proporcionar servidores de compilación :
Y luego abra esos servidores de compilación para los contribuyentes. Deben poder iniciar sesión de forma remota en una nueva imagen de Docker y editar, compilar y probar de forma remota en esta máquina.
Entonces:
En general, los servidores de compilación pueden compartirse entre múltiples contribuyentes, sin embargo, cuando se trata de periféricos de hardware especiales, puede ser necesario que un contribuyente use dicho periférico por sí mismo.
Fuente: trabajando en software que utiliza FPGA, dado el precio de las bestias y la variedad de modelos que necesitamos, no encuentra cada modelo de FPGA instalado en la máquina de cada desarrollador.
fuente
Si contribuir al núcleo sin cambiar ningún contrato puede romper el software dependiente, sugiere que:
Cualquiera de los problemas debería ser fácil de resolver, pero usted menciona que el equipo central podría no tener la capacidad para hacerlo. Una opción sería pedir ayuda a la comunidad para abordar el problema.
fuente
Nadie más parece haber planteado esto como una posible solución.
Al desarrollar el núcleo, aliente a los desarrolladores a ejecutar estas pruebas de compatibilidad. Si fallan, no se registre.
Esto no garantizará al 100% la compatibilidad, pero detectará muchos más problemas y pronto.
Un beneficio secundario es que estas grabaciones pueden resaltar qué interfaces se usan activamente y qué características se usan activamente.
fuente
Tengo problemas para entender la situación como parece ser: ¿el CI solo crea una rama?
¿Hay alguna razón por la que no puede construir más de una rama con el CI?
La solución más simple a este problema sería hacer posible que cualquier contribuyente ejecute la compilación de CI en su rama de características .
Luego, simplemente necesita una compilación de CI exitosa en la rama de características para que se acepte la solicitud de extracción de esa rama.
fuente