El futuro de la integración continua

15:31 0 Comments

Hace unos días estaba leyendo de nuevo el libro "Continuous integration" de Paul Duvall. Creo que es una lectura muy interesante, especialmente si usas métodos ágiles.

El libro es de mediados de 2007, así que es bastante nuevo, y hay un capítulo al final que me sorprendió. Se titula "el futuro de la integración continua" y se centra en dos preguntas interesantes:


  • ¿Cómo se pueden prevenir la el que se rompa una versión?
  • ¿Cómo se pueden hacer las versiones más rápido?

    La primera pregunta no nos preocupa internamente en Códice pero la segunda es probablemente uno de los mayores problemas que tenemos aquí en Códice ¿Se puede solucionar con un control de versiones?

    El autor comienza examinando la primera pregunta: ¿se puede prevenir el que se rompa una versión?, y si es así, ¿cómo? Bueno, pues aquí dice algo que me sorprende:

  • Imaginemos que la única actividad que un desarrollador necesita realizar es commit de su código en el sistema de control de versiones. Antes de que el repositorio acepte el código realiza una integración en otro equipo.

    Sólo se subirá el código al repositorio si la integración de la nueva versión se realiza correctamente. Esto puede reducir significativamente el problema de versiones que se rompan y puede reducir la necesidad de realizar integraciones manuales.



    Entonces dibuja un gráfico que representa una "integración en cadena lineal automatizada". Incluye algo como la protección del código en dos fases, por lo que el código no llega a la línea principal hasta que hayan pasado los tests...



    No se si se me olvida algo ya que creo que es una respuesta demasiado obvia, algo que todos los usuarios de Plastic se saben de memoria... proteger a una rama separada, hacer un rebase desde la rama principal, pasar las pruebas y solo integrar (copiar hacia arriba) si se pasan las pruebas...Ramificar es la respuesta, ¿no?
    Quiero decir, no podía entender una configuración tan "futurista" con un escenario de commit de dos fases, si esto es precisamente es lo que ya tienes con sistemas con un buen soporte de ramas.

    Entiendo que dice "la única actividad que un desarrollador tiene que hacer es commit de sus cambios", su problema no es simplemente el proteger los cambios sino el tener un lugar en el que el código pueda estar en una especie de estado intermedio y que mientres se estén realizando las pruebas el desarrollador pueda continuar trabajando.

    De nuevo debo de estar perdiéndome algo aquí, ya que sólo veo un motivo de "mejora para un futuro": el autor está siempre pensando en desarrollo en la línea principal (trabajar sólo con la rama principal o como mucho unas pocas más y directamente proteger los cambios en esta rama principal). Si estás acostumbrado a patrones como el de "rama por tarea", entonces no tendrás este problema. Estarás acostumbrado a incluir tus cambios en el control de versiones y continuar trabajando en otra cosa sin corromper la línea principal.



    Él continúa diciendo:

    Una alternativa puede ser dar al desarrollador la capacidad de realizar una integración utilizando una máquina dedicada a integrar nuevas versiones con sus cambios locales (que no han sido aún incluidos en el repositorio del control de versiones), junto con otros que se hayan incluido en el repositorio del control de versiones.


    ¡Pues claro que lo es! Por esto es por lo que rama por tarea es mejor alternativa que el desarrollo a la línea principal para casi cualquier escenario de desarrollo que he visto en mi vida.

    El problema detrás de estas afirmaciones tiene un nombre: los controles de versiones más conocidos (incluyendo el glorificado Subversion, que es la herramienta en la que se centra el libro) tienen enormes problemas gestionando ramas. No siempre fallan al crear un gran número de ramas (que es lo que me dicen los usuarios de SVN o CVS cuando menciono que Plastic puede gestionar miles de ramas..."mi sistema también"), el problema es gestionarlas después de unos cuantos meses (en el día de las pruebas todo funciona bien, ¿no?), hacer integraciones, comprobar lo que se ha modificado en la rama, seguir la evolución de las ramas, etc. Y, crean o no (y este es el motivo inicial de que crearamos Plastic), todas estas herramientas muy utilizadas y conocidas y a veces gratuitas, carecen de métodos adecuados de visualización, herramientas adecuadas para realizar integraciones (bueno, en algunos casos hay herramientas de terceros que se pueden integrar) y a veces incluso carecen de características básicas como seguimiento de integraciones o renombrado de ficheros.

    Supongo que este es el motivo por el que después de 200 páginas de una buena lectura encuentro un capítulo tan obvio que describe como innovación del futuro algunas de las prácticas más utilizadas en SCM. Yo recomendaría ir al clásico Software Configuration Management Patterns, que aún considero el libro de SCM mejor escrito.

    La pregunta de cómo agilizar las pruebas sigue sin respuesta...

    0 comentarios:

    Trabajo distribuido con Plastic

    12:31 0 Comments

    Una de las nuevas características más importantes de Plastic SCM 2.0 es el sistema distribuido. Hoy voy explicar la configuración que utilizo para trabajar desde mi portátil, desconectado de la red; y de cómo utilizo el sistema distribuido para sincronizar cambios.

    Esto es exactamente lo que me encanta del sistema distribuido: no es sólo útil para grandes equipos de desarrollo que trabajen en diversas localizaciones, también ayuda a los desarrolladores a poder trabajar desde sus portátiles...¡aunque formen parte de equipos pequeños!

    Mirad la siguiente figura: es un diagrama de implementación de diversos servidores que estamos utilizando aquí en nuestra oficina. Por supuesto que todos estos repositorios podrían estar en un único servidor, pero hemos configurado un escenario con múltiples servidores para probar las capacidades de Plastic diariamente.








    Como podéis ver en la imagen, tenemos tres servidores de repositorios, dos de ellos funcionando en Linux/Mono y un tercero en Windows. El servidor de windows (mordor) además funciona como servidor de espacios de trabajo, así que es el que hemos configurado como servidor de espacios de trabajo en nuestros ordenadores. Con lo que mi selector de espacios de trabajo tendría un apariencia más o menos así:


    rep "cmuser" mount "/06cmuser"
    path "/"
    label "BL091"

    rep "importers" mount "/05importers"
    path "/"
    label "BL091"

    rep "licensetools" mount "/04licensetools"
    path "/"
    label "BL091"

    rep "pnunit" mount "/03pnunit"
    path "/"
    smartbranch "/main/SCM2937"

    rep "nervathirdparty" mount "/02nervathirdparty"
    path "/"
    label "BL091"

    rep "codice"
    path "/"
    smartbranch "/main/SCM3278"
    Si, ¡6 repositorios montados en el mismo espacio de trabajo!

    Si os fijáis detenidamente veréis una regla a la que posiblemente no estéis acostumbrados...si, la regla del selector de smartbranch...Ya está en funcionamiento en Plastic 2.0 aunque aún no hemos sacado información pero escribiremos más sobre esta característica en breve, ahora es el momento de centrarnos en el sistema distribuido:-P

    Cuando trabajo desde casa suelo conectarme a la oficina por VPN, y luego trabajo con el portátil igual que si estuviese en la oficina. Nada cambia...pero de vez en cuando la red deja de funcionar...lo cual no es un problema trabajando con Visual Studio (soporte para trabajo sin conexión) o si continúas trabajando en la misma tarea (se puede seguir haciendo cambios, buscando los ficheros modificados cuando se recupere la conexión y desprotegiendo todo). Pero, ¿qué pasa si no tienes conexión a internet y quieres crear nuevas ramas o cambiar de una rama a otra?

    Pues ese es el motivo por el que he instalado un servidor de Plastic en mi portátil y utilizo el sistema distribuido para seguir trabajando incluso cuando la red deja de funcionar.

    He configurado un servidor en mi ordenador (beardtongue) en el puerto 6060. En este momento estamos utilizando el método de autenticación de usuario/contraseña por lo que he puesto el mismo método de identificación en mi servidor, aunque podría utilizar uno diferente y la replicación funcionaría igual (ver el manual del sistema distribuido).





    Una vez que está configurado, recordad que el cliente tiene que apuntar al servidor adecuado. Para esto se puede editar a mano el fichero client.conf file (en documents & settings si eres usuario de windows) o run plastic --configure.

    Los repositorios que necesito utilizar diariamente son codice (en el que está el código de plastic), thirdparty (librerías y cosas parecidad) y pnunit (nuestro sistema de pruebas); por lo que después de configurar mi servidor he creado tres repositorios vacíos denominados "codice", "thirdparty" y "pnunit" en mi servidor:


    $ cm mkrep localhost:6060 codice
    $ cm mkrep localhost:6060 pnunit
    $ cm mkrep localhost:6060 thirdparty


    Una vez que se han creado, he replicado la rama principal de los tres repositorios en mis repositorios locales:




    $ cm replicate br:/main@rep:codice@venus:9090
    rep:codice@localhost:6060
    $ cm replicate br:/main@rep:pnunit@juno:9092
    rep:pnunit@localhost:6060
    $ cm replicate br:/main@rep:thirdparty@venus:9090
    rep:codice@localhost:6060

    En mi caso la replicación de la rama principal tarda un poco la primera vez.
    La razón es que está realmente copiando todas las revisiones, los changesets, etiquetas y datos de la rama principal a mi repositorio local, y tenemos más de 1Gb sólo en las ramas principales de todos los repositorios.

    Una vez que la replicación ha terminado tengo todo el historial de las ramas principales de los tres repositorios en el servidor de mi portátil. Hay otro modo de llevar a cabo la replicación y requiere utilizar lo que llamamos paquetes de replicación. Imaginemos que por algún motivo mi portátil no puede acceder a uno de los servidores, por ejemplo, a venus. Entonces podría ir a una máquina con accesos y ejecutar


    $ cm replicate br:/main@rep:codice@venus:9090
    --package=replication.pack


    Que implica que la replicación creará un paquete con todos los datos para la rama br:/main.

    Una vez que haya terminado, podría copiarlo en una memoria usb y pasarlo a mi portátil, en éste ejecutaría



    $ cm replicate rep:codice@localhost:6060
    --import=replication.pack

    Para importar los datos a mi repositorio.

    Hasta ahora he configurado un servidor en mi portátil y tengo una copia completa de las ramas principales de los repositorios con los que necesito trabajar diariamente.

    Entonces crearé un espacio de trabajo y configuraré un selector como el siguiente (claro que las cosas son más sencillas si se utiliza un sólo repositorio):




    rep "pnunit" mount "/03pnunit"
    path "/"
    label "BL091"

    rep "nervathirdparty" mount "/02nervathirdparty"
    path "/"
    label "BL091"

    rep "codice"
    path "/"
    label "BL091"

    Y se configura un espacio de trabajo para poder compilar y depurar BL091.

    Bien, pero el sentido del sistema distribuido no está tan sólo en poder trabajar en modo lectura, sino hacer modificaciones.

    Si tengo que trabajar en la tarea 4312. Entonces crearía una rama Then -4312 (desde la GUI o desde línea de comandos, dependiendo de cómo se quiera trabajar), y configuraría el siguiente selector





    rep "pnunit" mount "/03pnunit"
    path "/"
    label "BL091"

    rep "nervathirdparty" mount "/02nervathirdparty"
    path "/"
    label "BL091"

    rep "codice"
    path "/"
    branch "/main/issue-4312" label "BL091" co "/main/issue-4312"


    Ahora podría hacer tantos ciclos de desprotecciones y protecciones como fueran necesarios y estarían en el servidor de mi portátil.

    En algún momento volveré a la oficina y querré incluir las ramas en el servidor real. En este caso he creado una rama para el repositorio codice, situada en venus:9090, así que hago lo siguiente:



    $ cm replicate
    br:/main/issue-4312@rep:codice@beardtongue:6060
    rep:codice@venus:9090

    Que replicará todos los cambios de la rama 4312 creada en mi portátil al servidor principal.
    También podría actualizar mis copias de las ramas principales ejecutando de nuevo los comandos de replicación desde los servidores del equipo, que ahora sería mucho más rápido que la primera vez.

    Pero, ¿que pasa si modifico la rama principal en mi portátil?, No habría ningún problema, depende totalmente del modo en el que se quiera trabajar, si queremos que todos puedan modificar la rama principal o no depende de cada equipo de trabajo. Si se hace así, ¿qué pasa si alguien modifica la misma revisión en el servidor principal a la vez?, tanto si se replica desde un portátil al servidor o viceversa, Plastic detectará que se a modificado una revisión en ambos lados. Creará una rama "fetch" que contenga los ficheros modificados en paralelo con lo cual los cambios se podrán sincronizar con una simple operación de integración...

    ¿Cuál es mi manera preferida de trabajar? Dependerá del escenario. "roaming developers" será mejor que trabajen en ramas separadas (nosotros lo hacemos continuamente con el patrón de rama por tarea) y utilizaría la rama principal como sólo lectura. Entonces incluirían los cambios en el servidor y actualizarían la rama principal para cada nueva versión.

    Esta es tan sólo una manera sencilla de conseguir sacar partido a los beneficios del nuevo sistema distribuido de Plastic SCM: utilizarlo para desarrollar desde un portátil incluso sin acceso a internet.

    ¿Qué será lo siguiente? Como habréis visto toda la funcionalidad del sistema distribuido está disponible a través de la línea de comandos, así que se incluirá en la interfaz gráfica en cuanto bastante pronto...

    0 comentarios:

    Paseo por el explorador de ramas

    12:10 2 Comments

    Es muy posible que alguna vez dibujéis un diagrama como este... (y apostaría a que seguramente lo hagáis con bastante frecuencia).




    Es simplemente un diagrama de ramas típico, que muestra las relaciones entre ramas, integraciones y etiquetas (los changesets normalmente no se muestran al dibujar un diagrama manual). Muestra claramente cuando se realiza una integración (desde el punto de vista de un proyecto) o el momento en el que se aplica una etiqueta (y por lo tanto una línea base).

    El gupo de Team System de Microsoft está planeando lanzar algo parecido en un futuro.



    ¡La buena noticia es que Plastic ya lo tiene! :-)

    El explorador de ramas incluido en la versión 2.0 de Plastic tiene todo lo necesario para representar la evolución de las ramas...el tipo de cosas que dibujaríais en un papel...pero ahora representado en la pantalla.




    Lo que ahora os vamos a mostrar es un paseo rápido por nuestro explorador de ramas y como se puede gestionar un ciclo completo de creación de ramas e integración desde el mismo.


    ¡Podéis ver el tour completo aquí! (tour en ingles)

    2 comentarios: