Un modelo de branching con «condimentos»

Desde hace años en mis desarrollos hago Trunk-Based Development (TBD) y también «evangelizo» en esta técnica. Pero lamentablemente me suelo encontrar que en muchos casos los equipos no se encuentran en condiciones para trabajar de esta forma. TBD requiere del uso simultáneo de un conjunto de técnicas complementarias sin las cuales su utilización resulta impracticable (o demasiado riesgosa). Obviamente que también están los «detractores» que creen que TBD «no funciona» o que «no es bueno», resulta curioso que muchos de estos detractores nunca probaron TBD seriamente.

En fin, el tema es que si no utilizamos TBD hay que buscar otra alternativa. Dos técnicas bastante populares en la actualidad son Gitflow y GitHub flow. Adicionalmente hay una práctica que he visto bastante difundida de asociar branches a ambientes la cual está bien para proyectos chicos/triviales pero que personalmente me parece inconveniente para proyectos más grandes/complejos.

Actualmente estoy colaborando con un equipo que digamos no está en condiciones de hacer TBD (o dicho de otra forma: al cual aún no logré convencer de hacer TBD). Sin embargo el modelo de branching que hemos acordado me resulta bastante convincente. La cuestiones es así:

  1. Para desarrollar cada funcionalidad se crear un branch (feature branch) a partir de la rama principal(main).
  2. En cada commit+push se ejecuta el linter y un conjunto de pruebas «unitarias/de componentes» automatizadas.
  3. Una vez el developer completa la funcionalidad (code complete), se genera un tag, una imagen docker y la misma es desplegada a un ambiente de prueba (existen varios ambientes de prueba) donde se realizan pruebas manuales.
  4. Al mismo tiempo se instancia un arnés de prueba armado con docker, donde se ejecutan un conjunto de pruebas de aceptación automatizadas.
  5. Si la prueba manual y las pruebas de aceptación automatizadas resultan exitosas, la rama es integrada en la rama principal, la imagen docker es promovida (no se la vuelve a buildear) y es desplegada a un ambiente de staging.
  6. En staging se realizan otro conjunto de pruebas (con datos más parecidos a los productivos) y todo está ok, la imagen se vuelve a promover y queda lista para ir a producción.

Si, es un clásico esquema de feature branch pero con «condimentos» que en muchos equipos no están presentes. Destaco aquí las pruebas automatizadas, el arnés de prueba «portable» creado con docker y el hecho de que la imagen docker se crea una única vez y es promovida a medida que pasa de un ambiente a otro.

No más .dlls en Git: infraestructura de desarrollo .Net

Una y otra vez me encuentro con equipos de desarrollo trabajando con tecnología .Net que guardan .dlls (librerías/packages) en repositorios de código fuente. Esto fue una práctica común en una época (lejana) y que yo mismo utilicé en algún momento. Pero desde la aparición de NuGet la gestión de librerías en en mundo .Net tomó un camino distinto.

Cuando uno tiene una dependencia de una librería a nivel binario, simplemente declara la dependencia en un archivo package.json y la herramienta NuGet se encarga de buscarlo en el repositorio binario y descargarlo. NuGet por default busca las librerías/paquetes en https://www.nuget.org/. Sin embargo hay dos casos donde seguramente no encontremos la librería en este repositorio:

  • Si estamos usando librerías de terceros, puede que por algún motivo esos terceros no hayan publicado el correspondiente paquete en nuget.org y dependiendo del tipo de licencia del paquete puede que no tengamos derecho a publicarlo nosotros mismos en un repositorio abierto.
  • Por otro lado es muy común hoy en día con el auge de los microservicios que uno tenga librerías propias que utilice en diversos proyectos de la organización y a menos que nuestros proyectos sean open source, es poco probable que querramos publicar esas librerías en nuget.org

Entonces, para estos dos casos la estrategia a seguir es utilizar un repositorio privado de binarios ya sea on-prem (instalando por ejemplo un Nexus) o utilizando algún servicio en la nube (como por ejemplo myget).

Si ponemos todo esto en contexto, una arquitectura de desarrollo de referencia podría incluir:

  • Un servidor de repositorios de código fuente, por ejemplo alguna implementación de Git como GitHub, GitLab o BitBucket.
  • Un servidor de CI/CD como Jenkins o TeamCity
  • Un servidor de repositorios de binarios NuGet como Nexus, MyGet o Artifactory

Estrategia de versionado para DevOps, paper aceptado

Hace unos días me notificaron que mi paper Versioning Strategy for DevOps Implementations fue aprobado para ser presentado en Congreso Argentino de Ciencias de la Informática y Desarrollos de la Investigación (CACIDI2018). Comparto aquí el resumen de este trabajo:

DevOps is one of the most popular approaches for software delivery nowadays. Even though there is no unified definition of DevOps, there is wide consensus about the set of practices that are part of it. Two of those practices areInfrastructure as Code and Continuous Delivery, which bring new artifacts into the Software Development lifecycle. These new artifacts have direct impact on Software ConfigurationManagement, which is a well-known practice that has been around for decades in the Software Engineering discipline. In particular, these new practices have a direct impact on VersionControl. This article describes a Version Control Strategy to manage these new artifacts introduced by DevOps initiatives.The proposed strategy covers the identification of artifacts, versioning tools, version naming conventions and traceability between different artifacts versions. The strategy was validated in three cases of real world projects where it was successfully applied. Each case corresponds to a different kind of organization and in each case a different set of tools where used. Based on these cases, benefits and possible improvements are identified.

Spring Config: a key tool for DevOps & Continuous Delivery

Spring Cloud Config (scc) is a tool that provides support to externalize application configuration in a REST Service. The big picture is:

  • Add a SCC client your application so when your application starts, it can fetch its configuration from SCC server.
  • Setup a SCC server, which is a Java REST Service (more specifically is a Spring-Boot application).

The following image offers a overview of how Spring Cloud Config fits in you application architecture.

Some benefits of this strategy are:

  • You decouple the evolution of your application from the evolution of the configuration, that is: you application will be the same in every environment while the configuration will be different in each environment. At the same time the change rate of your application is different from the change rate of the configuration.
  • Your application forgets about where the configuration it stored because it delegates that concern to SCC server.
  • SCC server supports several storage options: Git, File System, Vault, Database, ConfigMaps, etc. The default option is Git which is great because it «force» you to have your configuration versioned.
  • SCC provides several common features related to configuration management like: check the current configuration values, configuration reloading, encryption of secrets and support for different configuration formats among other things.

While working with SCC I faced some issues regarding how to specify its configuration so I want to share some details here.

To make SCC Server read configuration from a remote Git repository:

spring.cloud.config.server.git.uri=https://.....

(this would work fine for public repositories, but if you need to use a private repository, which is a common case, you will need to specify some more parameters like strictHostKeyChecking and privateKey that are very well explained in the official documentation). When SCC server starts, it will clone the remote repository into a local directory whose location will be generated randomly at runtime (but it is also possible to specify the clone location).

To make it work with a local git repository (which contains a .git subdirectory), just use:

cloud.config.server.git.uri=file:///your/local/git/repo

To make ir work with a local «plain» directory we need to specify active profile as «native» which makes SCC server to read the config from a plain local directory (not a git directory)

spring.profiles.active=native
spring.cloud.config.server.native.searchLocations=file:/your/directory

It worth mentioning that even when Spring Cloud Config is built on Java, you can use any client technology to consume it because it exposes a REST API. The Spring team provides a Java client, but there are also clients for other technologies.

 

PCE-Evolution: An infrastructure pattern

Beyond which environments I use on different project/organisation there is one recurrent strategy that I have applied several times in different context. I may say it is a pattern.

The problem

Like any pattern explanation it should start with a problem, so here it is: it is very common production environments to be large in term of hardware capacity and also in size of data. This makes difficult (and/or very expensive) to replicate the production environment to test your application. If you test in an environment different from the production environment you are taking a risk, and the bigger the difference is the higher the risk you are taking.

The solution

Your application pass through different environments from you local development machine to the final production environment.  These two environments are the extremes of your pipeline, so you should make use that each intermediate environment is «closer» to the production environment.

Example

Local development environment (your workstation): here you run the whole application in an isolated way, you have a local DB installed and external services dependencies may be mocked. Your hardware is not comparable to production’s hardware. Even your OS may be different: you may use Windows 10 or Mac or Ubuntu Desktop, while your production server may run Windows Server or Ubuntu Server. In terms of the previously mentioned dimensions, all of them are different from production.

Development environment: your hardware is still far from production, but at least you have the same OS asp production but the other dimensions are still different.

Test Environment: here your layout is the same as production, that is: if you have a cluster for the production DB, then you also have a cluster for test DB but possibly your test DB cluster has less servers that the production one.

This way the closer to production the more Production-like, Complex and Expensive.

infra_pattern

Taller de Git online (experimento gratuito)

Desde hace ya un par de años vengo incursionando en la educación online pero siempre en calidad de estudiante. Si bien en las materias que dicto suelo hacer uso de varios recursos online, el dictado formal sigue siendo presencial. La idea de hacer algo online me viene picando desde hace tiempo y esta semana finalmente decidí hacer mi primer experimento.

La temática será Git, una herramienta con la que vengo trabajando desde 2009 y aunque inicialmente no me gustó, desde 2011 la adopté como mi controlador de versiones preferido. Desde ese momento he realizado diversas actividades de difusión: cursos, charlas, artículos, etc. Ahora ha llegado el momento de tomar todos los materiales generados en estos años para darle forma a un curso online.

La idea es generar un conjunto de videos cortos (de entre 5 y 10 minutos) y complementarlos con ejercicios y lecturas además de ofrecer algunas sesiones online para consultas(posiblemente via Hangout o Skype). Mi idea es que el curso pueda completarse en unos 10 días, con una carga de trabajo de 30 minutos diarios.

Mi intención es largar la primera corrida experimental el lunes 20 de Abril. Si estas interesado en participar te pido que completes este formulario para que podamos coordinar el horario de los sesiones de consulta. Este primer experimento será totalmente gratuito.

Elegir un sistema de control de versiones

En más de una ocasión he sido consultado por organizaciones sobre la elección de sistemas de control de versión. Actualmente estoy trabajando con una organización que usa CVS y que está evaluando distintas herramientas para reemplazarlo.

Si bien basta con googlear un poco para encontrar miles de post sobre las diferencias, beneficios y problemas de los distintos sistemas de control de versiones, cambiar el sistema de control de versiones implica varias cuestiones no triviales.

Desde mi perspectiva estamos hablando de una herramienta que nos ayudará a resolver ciertas cuestiones de trabajo colaborativo y recalco esto: nos ayudará, la herramienta por sí sola no resolverá nada. Más aún, una herramienta mal utilizada puede traer más problemas que soluciones. Para que la herramienta nos permita resolver algún problema, debemos establecer ciertas reglas/convenciones para su uso (y luego respetarlas).

Dicho esto, deberíamos comenzar por identificar el/los problemas a resolver y luego analizar cómo es que cada alternativa de herramienta nos permitiría resolver esas cuestiones.

Desde mi óptica, hay 3 dimensiones de considerar en la evaluación.

Sistema de control de versiones: Git, Subversion, CVS, Mercurial, Darcs, son algunos sistemas de control de versiones. Para elegir uno posiblemente debamos comenzar por preguntarnos si queremos un sistema distribuido o centralizado y con ese punto de partida podremos ir acotando nuestras opciones. No voy a profundizar sobre este punto pues considero que es el que más desarrollado está y basta googlear un poco para encontrar pros y contras de cada uno.

Producto/Servicio: una vez elegido el sistema debemos elegir un producto o servicio que lo implemente. En este caso la discusión podría comenzar por: ¿queremos tener el sistema en nuestra infraestructura o preferimos contratarlo como servicio?. Una vez definido esto deberemos elegir un opción concreta. Ejemplo: supongamos que decidimos ir un sistema distribuido y concreto nos inclinamos por Git, entonces podríamos utilizar un servicio en la nube como el ofrecido por GitHub o Bitbucket o bien podríamos decidir adquirir un producto e instalarlo en nuestro entorno como podria ser GitLab o Stash.

Forma de uso: por más que hayamos elegido una producto/servicio concreto (supongamos GitLab), aún no basta para resolver nuestro problema, deberíamos definir ciertas cuestiones respecto de cómo usarlo. Esto implica responder preguntas tales como: ¿Cuál es el criterio para la creación de repositorios: creamos un único repo por equipo o creamos un repo por componente de nuestra solución? ¿usamos branches o forks? ¿cómo debería ser la estructura de cada repositorio?¿trabajamos todos sobre master o usamos feature branches?. Sin duda varias de estas cuestiones estarán influenciadas por la herramienta elegida pero más allá de eso, hay otra cuestiones que dependerán de problemática concreta de cada organización/proyecto.

En los últimos 2 años, he trabajado con al menos 5 organizaciones y en todos los casos la herramienta elegida ha sido Git. Si bien no siempre participé directamente en la elección de la herramienta, en varios casos estuve fuertemente involucrado en la definición de la forma de uso y la capacitación de los equipos.

Webinar: Técnicas de versionado para Entrega Contínua

El próximo miércoles (mañana), voy a estar dando un webinar sobre este tema. La idea es ver los conceptos básicos de la práctica Continuous Delivery y enfocarnos en cómo manejar nuestro repositorio de código para facilitar la entrega continua. Presentaremos algunos conceptos y estrategias, y veremos como llevarlos a la práctica utilizando la herramienta Git.

En página de registración encontrarás más detalles sobre este webinar.

Durante el webinar, recibiré consultas a través de Twitter (@kleer_la & #kleerScm).