Estructura del repositorio Mercurial con comunicaciones corporativas pesadas, gestión de configuración y requisitos de prueba

15

Todavía soy otro usuario de Subversion que lucha por reeducarme en el Tao del control de versiones distribuido.

Al utilizar Subversion, era un gran fanático del enfoque de proyecto menor y, con la mayoría de mis empleadores anteriores, estructurábamos nuestras sucursales de repositorio; etiquetas & tronco de la siguiente manera:

branches-+
         +-personal-+
         |          +-alice-+
         |          |       +-shinyNewFeature
         |          |       +-AUTOMATED-+
         |          |                   +-shinyNewFeature
         |          +-bob-+
         |                +-AUTOMATED-+
         |                            +-bespokeCustomerProject
         +-project-+
                   +-shinyNewFeature
                   +-fixStinkyBug
tags-+
     +-m20110401_releaseCandidate_0_1
     +-m20110505_release_0_1
     +-m20110602_milestone
trunk

Dentro del propio árbol de origen, usaríamos (algo como) la siguiente estructura:

  (src)-+
        +-developmentAutomation-+
        |                       +-testAutomation
        |                       +-deploymentAutomation
        |                       +-docGeneration
        |                       +-staticAnalysis
        |                       +-systemTest
        |                       +-performanceMeasurement
        |                       +-configurationManagement
        |                       +-utilities
        +-libraries-+
        |           +-log-+
        |           |     +-build
        |           |     +-doc
        |           |     +-test
        |           +-statistics-+
        |           |            +-build
        |           |            +-doc
        |           |            +-test
        |           +-charting-+
        |           |          +-build
        |           |          +-doc
        |           |          +-test
        |           +-distributedComputing-+
        |           |                      +-build
        |           |                      +-doc
        |           |                      +-test
        |           +-widgets-+
        |                     +-build
        |                     +-doc
        |                     +-test
        +-productLines-+
        |              +-flagshipProduct-+
        |              |                 +-coolFeature
        |              |                 +-anotherCoolFeature
        |              |                 +-build
        |              |                 +-doc
        |              |                 +-test
        |              +-coolNewProduct
        +-project-+
                  +-bigImportantCustomer-+
                  |                      +-bespokeProjectOne
                  |                      +-bespokeProjectTwo
                  +-anotherImportantCustomer-+
                                             +-anotherBespokeProject

La idea era (y sigue siendo) utilizar la estructura del repositorio para ayudar a estructurar la comunicación entre el equipo de ingeniería; la parte del negocio orientada al cliente y otras partes interesadas & expertos de dominio.

Para saberlo: los documentos de origen que se encuentran en uno de los directorios de "proyectos" se utilizan (y ganan dinero) solo una vez. Los documentos que se encuentran en uno de los directorios de "productLines" ganan dinero tantas veces como se vende un producto de esa línea en particular. Los documentos que se encuentran en uno de los directorios de las "bibliotecas" ganan dinero tantas veces como se venden los productos que los usan.

Hace que la noción de amortización de los costos sea explícita y ayuda a desarrollar el soporte para la reutilización de documentos de origen en toda la empresa.

También significa que existe una estructura común sobre la cual pueden operar nuestras herramientas de automatización de compilación. (Nuestros scripts de compilación recorren el árbol de origen en busca de carpetas de "compilación" en las que encuentran archivos de configuración que especifican cómo se debe construir cada componente; ocurre un proceso similar para la generación y prueba de documentación).

Significativamente, los productos en los que trabajo normalmente tardan mucho tiempo en ejecutar la medición de rendimiento y amp; pruebas de caracterización; de 20 a 200 horas; generar en algún lugar entre varios GB a varios TB de resultados de prueba procesados / datos intermedios (que deben almacenarse y vincularse a una configuración particular del sistema para poder medir la mejora del rendimiento a lo largo del tiempo). Este problema hace que la administración de la configuración sea una consideración importante, y también impone algún requisito para la centralización, ya que, por lo general, los recursos computacionales necesarios para ejecutar las pruebas de caracterización y medición de rendimiento son limitados; (un pequeño grupo de 64-128 núcleos).

Como una nota final; el sistema de integración continua sabe que necesita desencadenar una compilación; análisis estático; prueba de humo & la prueba de la unidad se ejecuta cada vez que se modifica el troncal, cada vez que se modifica una rama "etiqueta", y cada vez que se modifica una rama "AUTOMATIZADA". De esta manera, los desarrolladores individuales pueden utilizar el sistema de CI con sus sucursales personales, una capacidad importante, en mi humilde opinión.

Ahora, aquí está mi pregunta: ¿Cómo puedo replicar todo lo anterior (y mejorarlo, si es posible), con Mercurial?

--edit:

Mi línea de pensamiento actual es usar un repositorio central de Subversion para definir la estructura general, pero para permitir el uso de hg como cliente para que los desarrolladores puedan tener repositorios disponibles localmente.

    
pregunta William Payne 04.01.2012 - 18:22

2 respuestas

9

La respuesta de Spoike es excelente, pero hay algunas cosas que creo que vale la pena agregar, que también son grande para comentarios.

Organización de la rama

Con Mercurial, puede ignorar felizmente la totalidad de su primer organigrama. Como dice Spoke, cada repositorio tiene su propio conjunto de etiquetas, sucursales (nombradas y anónimas) y puede organizarse según las necesidades de la empresa.

Si bespokeProjectTwo necesita una versión especial de la biblioteca charting , entonces ramificaría charting , agregaría las nuevas instalaciones y las usaría en bespokeProjectTwo . Las nuevas instalaciones (y sus errores) no serían utilizadas por otros proyectos que harían referencia a la biblioteca estándar charting . Si la biblioteca principal charting tenía errores corregidos, podría combinar esos cambios en la rama. Si otros proyectos también necesitaran estas instalaciones, puede hacer que esos proyectos utilicen la rama especial , o fusionar la rama con la línea principal y cerrar la rama.

Además, no hay nada que le impida tener una política para estructurar nombres de sucursales para proporcionar instalaciones específicas como sus sucursales de AUTOMATION.

Organización del directorio

No hay ninguna razón por la que no pueda mantener su directorio de origen exactamente como está con Mercurial. La única diferencia es que mientras que con Subversion tienes un solo repositorio monolítico (src) , con Mercurial es mejor dividir en repositorios que están agrupados lógicamente. De su estructura de árbol de origen, probablemente extraería cada uno de los siguientes como repositorios individuales:

src-+
      +-(developmentAutomation)
      +-libraries-+
      |           +-(log)
      |           +-(statistics)
      |           +-(charting)
      |           +-(distributedComputing)
      |           +-(widgets)
      +-productLines-+
      |              +-(flagshipProduct)
      |              +-(coolNewProduct)
      +-project-+
                +-bigImportantCustomer-+
                |                      +-(bespokeProjectOne)
                |                      +-(bespokeProjectTwo)
                +-anotherImportantCustomer-+
                                           +-(anotherBespokeProject)

Esto permite que cualquier producto o proyecto a medida use cualquier combinación de bibliotecas, en cualquier revisión. Eche un vistazo a sub-repositorios mercurial para ver qué bibliotecas se utilizan para cualquier versión de un producto o proyecto.

Flujo de trabajo

Una alternativa al flujo de trabajo sugerido por Spoike (el desarrollador extrae de blessed repo, trabaja localmente, emite una solicitud de extracción y, finalmente, el integrador extrae esos cambios y los combina) sería utilizar el sistema de integración continua como intermediario.

Como antes, el desarrollador saca del repo bendecido y trabaja localmente, pero cuando termina, tira del repo bendecido otra vez y se fusiona antes de pasar a un repo sin bendición. Todos los cambios en el repositorio sin bendiciones se revisan (de forma manual o automática) y se mueven al repositorio bendecido solo si se aprueban.

Esto significa que el integrador solo tiene que aceptar o rechazar un cambio, no hacer la fusión. En mi experiencia, casi siempre es mejor para el desarrollador que escribió el código para realizar la combinación que para que otra persona lo haga.

Como se sugiere en el libro comercial, se pueden utilizar ganchos para automatizar este procedimiento:

  

Cuando alguien inserta un conjunto de cambios en el servidor del que todos sacan, el servidor probará el conjunto de cambios antes de que lo acepte como permanente y lo rechazará si no pasa el conjunto de pruebas. Si las personas solo obtienen cambios de este servidor de filtrado, esto servirá para garantizar que todos los cambios que las personas obtienen se hayan revisado automáticamente.

Otros problemas

El problema de los grandes conjuntos de datos de prueba también se puede resolver al colocar esos datos de prueba en un sub-repositorio mercurial . Esto evitará que el repositorio de códigos se hinche con los datos de prueba, mientras se mantienen los datos de prueba bajo control de revisión.

    
respondido por el Mark Booth 05.01.2012 - 12:55
8

Está bien, tratando de responder a esto simplemente.

Lo que necesitas saber

Lo primero que debe saber: Mercurial es un control de versión distribuido y tiene algunas propiedades que debe conocer que se enumeran a continuación.

  • La fuente proviene de un repositorio, donde se puede clonar ese repositorio. Todos los repositorios clonados pueden compartir código entre sí mediante la sincronización (con comandos de extracción y inserción, que pueden tener acceso restringido).
  • Cada usuario que tiene una copia del código, tiene un clon del repositorio. Si quieren ramificarse, pueden hacerlo en su clon local. Eso significa que no es necesario organizar la forma en que cada usuario debe dividirse. Pueden hacerlo por sí mismos.
  • Las etiquetas se crean en mercurial por un commit (que es lo mismo que las etiquetas duras en git). Esto significa que no necesita un directorio dentro de su estructura de repositorio para las etiquetas.
  • El modelo habitual con el que trabaja la gente en DVCS (que se emplea en github y bitbucket) es hacerlo semi-centralizado.

    Cada usuario tiene un repositorio público (en algún recurso compartido o en un servidor seguro) y un repositorio privado (en sus propias estaciones de trabajo). Ambos son clones del repositorio "bendito" de un integrador. Cuando sienten que están listos para publicar su código, pueden enviar los cambios a su repositorio público. Un integrador puede entonces elegir qué usuarios incluirán el código en el repositorio "bendito".

    Si el integrador no puede combinar el código de algunos usuarios con facilidad, los cambios se rechazan y el usuario en particular debe actualizar su repositorio y arreglar la fusión por sí mismos. Por lo general, no es tan difícil si se fusiona a menudo (ya que es menos el código que debe fusionarse) y, por lo general, ese usuario debería saber qué fue lo que falló en la combinación.

Configuración de repositorios por proyecto

Por lo tanto, la configuración habitual es que para cada proyecto hay lo siguiente:

  • Un repositorio público de solo lectura del cual el integrador es responsable. Es "bendito".

    I.e. todos los usuarios pueden extraer / obtener contenido, pero no tienen acceso para hacerlo.

  • Cada usuario puede tener su propio clon público del repositorio.

    La configuración más fácil es ponerla en una unidad compartida (aunque puede considerar hospedar como bitbucket). El integrador recibe solicitudes de extracción de los usuarios e intenta extraer el nuevo código de estos repositorios. Cuando las fusiones se realizan sin problemas, se coloca en el repositorio de solo lectura. De lo contrario, se les pide a los usuarios que corrijan los conflictos de combinación que surgen al actualizarlos y fusionarlos localmente.

  • Cada usuario puede tener sus propios clones privados del repositorio.

    Una buena práctica es sacar de su clon público, pero no importa si ellos sacan de su público o del integrador. Todas las confirmaciones son identificables de manera única, por lo que la combinación de confirmaciones que se olvidó de buscar en la pública es relativamente fácil de arreglar (al impulsar los cambios de lo privado a lo público, también se obtienen automáticamente los cambios del integrador).

Organización del código fuente

Al igual que en cómo organizar la fuente del proyecto en sí mismo, es algo que debe considerar. Si un artefacto necesita ser controlado por fuente, entonces póngalo en control de fuente. Personalmente, no me gusta la idea de comprobar los artefactos creados por la compilación o el tiempo de ejecución (debido al alto riesgo de conflictos de combinación en este tipo de artefactos) como binarios o archivos de registro.

También puede verificar la configuración, siempre que faciliten a los desarrolladores ponerse en marcha y no arruinen la configuración de las versiones o el entorno en vivo / de producción (como la configuración de la aplicación / servidor web). Esto lleva a la noción de que si la configuración que tiene obstaculiza seriamente que los desarrolladores comiencen dentro de los cinco minutos posteriores a haber comprobado el código, entonces debe ser refaccionado. Otro requisito es que debería ser muy difícil para los desarrolladores desordenar el lanzamiento o el entorno de producción / producción.

Usted menciona que tiene datos de prueba que deben estar vinculados a alguna versión del código. Ahora esto es un poco más complicado porque los sistemas DVCS como Mercurial y Git tienen una tendencia a disminuir cuando se registran datos que son GRANDES. En mi experiencia, se vuelve realmente insoportable después de 5 GB de archivos binarios (su kilometraje puede variar, por lo que debe probar cómo funciona para usted). Sin embargo, recomendaría que coloque los datos generados en su propio repositorio y haga que su sistema de prueba los etiquete adecuadamente al registrarlos (y / o cree archivos de texto para los mismos metadatos).

Espero que todo esto tenga sentido. Comente a continuación si me he perdido algún detalle o si hay que explicar algo más y trataré de editarlo.

    
respondido por el Spoike 04.01.2012 - 22:14