miércoles, 28 de diciembre de 2022

Trucos Git: "Commitea" con el usuario correcto

¿Trabajas con varias cuentas de Git en diferentes proveedores? ¿Quizás GitHub, Azure DevOps, Bitbucket u otros?

 

Si es así seguro que te ha pasado algo muy molesto: haces los commits con el usuario erróneo. Esto sucede porque normalmente el nombre y el mail con el que hacemos nuestros commits se establece de forma global (al instalar Git en el equipo por ejemplo) y se usa con todos los commit, esté donde esté el repositorio remoto. 

 

Estos datos nada tienen que ver con la autenticación contra tu proveedor, así que aunque mi usuario en Azure DevOps fuese sergio@midominio.com, yo podría commitear como sergio@otrodominio.com

 

Vamos a verlo con un ejemplo


Commiteando con el usuario equivocado

 

Voy a clonarme un repositorio que tengo en GitHub:


            git clone https://github.com/snavarropino/CacheSleeve.git 

 

Una vez hecho esto, voy a setear mi configuración de Git, eligiendo un usuario erróneo:

 

 

git config --global user.name "wrong user"
git config --global user.email "sergio@wrongdomain.com"

 

Y seguidamente haré un commit y lo subiré al repo

 

echo hi > mychange.txt
git add .\mychange.txt
git commit -m "Added my change"
git push

 

Si revisamos la historia, tanto en local como en remotlo, vamos a ver que el commit queda "atado" a ese "wrong user". ¿Un poco loco verdad?

 



 

Aquí he forzado el error, pero lo que suele pasar es que estableces la configuración para commitear por ejemplo en Azure Devops (trabajo), luego te clonas un repo de GitHub, y al commitear va la info del trabajo en vez de la de tu cuenta personal en GitHub... 

 

¡Me pasa constantemente! Vamos a solucionarlo.

 

Forzando que cada repo tenga configuración local

 

Desde git versión 2.8 (ha llovido ya) tenemos la opción de forzar que deban configurarse usuario y email en cada repo, de modo local a este.

Esto lo conseguimos así

 

git config --global --unset-all user.email
git config --global --add user.useConfigOnly true

 

Una vez hecho esto, si en un repositorio en el que no hemos configurado localmente hacemos un commit, obtendremos un error. Ya no se usará más la configuración global.

 


 

Ahora tendremos que configurar el nombre y el email apropiado para cada repo, es más tedioso pero evitamos errores. ¿Cómo lo hacemos?


git config --local user.email sergio.navarropino@gmail.com

git config --local user.name "Sergio Navarro Pino"

 

Espero que os resulte útil y que evitéis esos molestos errores

 

Saludos! 


PD: Jose María Flores Zazo ya escribió sobre este tema, el lo resuelve con GitKraken, interesante!

https://jmfloreszazo.com/git-mejores-practicas-informacion-del-usuario

miércoles, 23 de marzo de 2022

Jekyll, Hugo, static site generators y otras petisoperias


El los últimos meses hemos visto como varios bloggers han cambiado de plataforma, bien saliendo de plataformas hospedadas por terceros (blogger por ejemplo), bien de instalaciones Wordpress hosteadas por ellos mismos.

Los motivos son varios, pero podríamos resumirlos en tres:

  • Abandono de la plataforma, algo que sucede en gran medida con blogger. Da la sensación de ser un proyecto que Google mantiene al ralentí, y ya sabemos que Google no duda un momento en cerrar servicios.

  • Propiedad de los contenidos: ¿Qué pasa si una plataforma cierra de un día para otro? ¿recuperaré mis contenidos? Mentiría si dijese que tengo un backup de todas mis entradas. En general el contenido lo tengo, pero sin formato, quizás sin imágenes, etc… ¡sería un desastre!

    Además podríamos hablar (no lo haré ahora) del "efecto Medium", una plataforma que cambió su modelo de negocio, pasando a cobrar a los lectores.

  • Dificultad de mantenimiento: esto aplica principalmente a Wordpress. Nunca he hecho nada serio con él, pero si he escuchado quejas al respecto, y no pocas. Cuando el río suena…

¿Dónde han ido esos bloggers?


Parece que el uso de generadores de sitios estáticos se ha impuesto (Hugo, Jekyll, Gatsby), alojando dichos sitios principalmente en GitHub Pages, aunque esta no es la única opción; podríamos hostear en Azure Storage, en GitLab Pages, también usando Azure Static Web Apps... hay muchas opciones válidas.

Hay mucha información al respecto, aquí os dejo unos enlaces:


Algunas de las ventajas son muy claras y directas: propiedad 100% del blog, cuyo código estará alojado en un repositorio Git de tu propiedad, con todos los beneficios que esto trae, como el control de versiones y la posibilidad de ejecutar pipelines para para diversas tareas (cross posting como ejemplo).

Por otro lado, el performance del site será buenísimo, difícilmente un motor dinámico puede competir con un sitio estático.


¿Y yo qué voy a hacer? ¿Voy a seguir en Blogger?


M apetece moverme, pero echo la vista atrás y veo que no he logrado publicar regularmente. Debo empezar a publicar con regularidad de nuevo, y si lo consigo, haré el movimiento. Hacerlo al revés me parece un error.

Por lo pronto me pongo a escribir la siguiente entrada, sobre git y mis problemas por usar múltiples cuentas. 

¿Y que es eso de las petisoperías?

 
Si has leido Superlopez, seguro que lo recuerdas
 

 

lunes, 7 de febrero de 2022

Feature flags o deployment rings. ¿Por qué no ambos?

DevOps nos permite entregar valor al negocio de un modo sostenido, obteniendo feedback de producción de un modo temprano, de modo que nuestras decisiones sean tomadas en base a datos objetivos.

 

Entregar features rápido no implica que todas estas features resulten siempre satisfactorias para nuestros usuarios o el negocio. Algunas pueden fallar (tener bugs) o pese a funcionar correctamente, no resultar útiles o cómodas a nuestros usuarios, generando rechazo.

 

En esos casos, una exposición progresiva (Progressive exposure) de estas nuevas features puede reducir el rechazo, o al menos que este se produzca en un número reducido de usuarios, en vez de en toda nuestra base de clientes.

 

El conjunto de usuarios a los que llega una nueva feature se conoce como Radius blast, por analogía con el radio de expansión de una bomba. Si decimos que incrementamos el Radius blast, estaremos haciendo que una feature llegue a más usuarios.



Feature flags y Deployment rings


Dos de las técnicas más extendidas que podemos usar para exponer nuestras features progresivamete a nuestros usuarios son el uso de feature flags y la estrategia de despligue en anillos (deployment rings).

 

Ambas cumplen el propósito, pero como no podía ser de otro modo, presentan pros y contras, que debemos conocer antes de "lanzarnos" a seleccionar una.


Deployment rings


Fueron descritos por primera vez por Jez Humble en el famosísimo libro "Continuous Delivery", donde se hablaba también de canary deployments, que podemos considerar un caso especial de despliegue en anillos.

 

Portada del libro Continuous Delivery

 

 

Se trata de disponer de varios entornos de producción, siendo cada uno de tus usuarios siempre enrutado al mismo entorno, por criterios variados (geográficos, por tipo de usuario, por antigüedad u otros).

 

Cuando se despliega una nueva feature, inicialmente solo estará disponible en el primero de los entornos (anillo), donde será visible solo para un porcentaje de usuarios (los redirigidos allí).

 

A partir de ese momento comenzaremos a monitorizar activamente el comportamiento de esta nueva feature en ese primer anillo, para pasado un tiempo razonable, decidir si la progresamos al siguiente anillo (hemos ganado suficiente confianza) o bien es necesario algún cambio en el software, y por tanto un nuevo despliegue al primer anillo.

 

Este mismo proceso lo realizaremos para cada uno de los anillos que hayamos definido. Podemos verlo en el siguiente gráfico:


Proceso de CI/CD con deployment rings


 

Como veis se han definido 3 anillos: al primero lo llaman "Canaries", el siguiente es para "Early adopters" y el último engloba al resto de usuarios. A modo de ejemplo, y para una aplicación tipo "Spotify" podríamos definirlos así:

 

  • Canaries: trabajadores de Spotify
  • Early adopters: Clientes que han indicado que quieren recibir versiones "beta"
  • Users: resto de usuarios

 

Podríamos definirlo de otro modo, con más o menos anillos y usando otros criterios como decía antes, pero lo importante es el proceso, que paso a detallar:

 

  1. Un commit llega a la rama principal
  2. Se dispara atomáticamente el pipeline de CI/CD
    1. Se compila, se pasan los tests y se empaqueta el software
    2. Se despliega en el primer anillo
  3. Se monitoriza activamente durante un tiempo definido
    1. Si se encuentra algun problema, se descarta la release y no será progresada a siguientes anillos
    2. Si no se encuentran problemas, se progresa la release al siguiente anillo. Podría ser con una acción de aprobación manual o de modo automático (cuando termina el tiempo definido)
  4. Se actúa igual en los siguientes anillos

 

Como vemos ganamos en confianza a coste de ser más lentos haciendo llegar las nuevas features a nuestros usuarios.


¿Qué herramientas podemos usar para implementar una estrategia de despliegue en anillos?

 

Sin duda mis favoritas son GitHub actions y Azure Pipelines, aunque podríamos usar otras como CircleCI, Jenkins o GitLab

 

En GitHub actions nos será muy útil usar environments (aunque solo están presentes en la versión Enterprise):

https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment


En Azure DevOps Pipelines, también nos apoyaremos en los environments, y además  disponemos de las Gates, que nos pueden ayudar a monitorizar nuestra release en un anillo para decidir si progresa al siguiente:

https://docs.microsoft.com/en-us/azure/devops/pipelines/release/approvals/

 

 

Feature flags (o feature toggles)

 

Fueron descritos por primera vez por Martin Fowler en este artículo y nos permiten desacoplar la exposición  progresiva de features del despliegue de una release. Para ello, las nuevas features van controladas con un toggle, que nos permite, en tiempo de ejecución, elegir si se encuentran activas o no, y por tanto modificar el comportamiento de nuestro software.

 


 

Es decir, podemos desplegar una release con varias features desactivadas, para más adelante activarlas poco a poco, monitorizando en todo momento su comportamiento.

 

 

¿Qué necesitamos para esto?

 

  1. Un servicio de gestión de toggles.
  2. Una query que pregunte en tiempo de ejecución el valor de un toggle
  3. Una remificación if-else (o algo más sofisticado) en nuestro código que haga que el software se comporte de distinta manera cuando el toggle esté o no activado.

 

¿Qué herramientas podemos usar?


Azure App Configuration nos ofrece una gestión simple de Feature toggles, que puede servir en algunos escenarios, pero lo más seguro es que rápidamente necesites algo más avanzado, como Xabaril Esquio (un paquete para .NET hecho por algunos amigos) o un servicio como LaunchDarkly.


¿Qué opción elegir?

 

Como siempre que se hacen este tipo de preguntas, sería temerario responder categóricamente, un "depende" siempre es más acertado.

 

En ambos casos vamos a controlar qué usuarios reciben features, para después ir exponiéndolas progresivamente a otros grupos de usuarios o la totalidad de estos. Además ambas opciones nos van a permitir realizar un A/B testing controlado.

 

No obstante hay algunas diferencias importantes que debemos conocer. 

 

Coste


Con Deployment rings vamos a necesitar varios entornos de producción, mientras que con Feature flags vamos a necesitar una herramienta para controlarlas (con un store para persistir las toggles), además de cambios en nuestro código para gestionarlas.

 

Para mí este último detalle es importante. Mantener muchas toggles no es gratis, tu código se ve afectado, y las toggles deben ser eliminadas una vez que hemos decidido que una feature nunca más será desactivada.

 

La deuda de toggles puede ser peligrosa, y debemos tener en cuenta que no se trata solo de borrar la toggle, sino la ramificación de código asociada. Por aquí hablan de ello: https://codescene.com/blog/feature-toggles-are-technical-debt/


Gestión del Radius Blast

 

Podemos pensar que es más sencilla con los Deployment rings, ya que se trata de enrutar a los usuarios al entorno adecuado según los hayamos categorizado (canaries, early adopter o usuario general en el ejemplo que presentaba).

 

Sin embargo las librerías y los servicios avanzados nos permiten definir grupos de usuarios y conseguir efectos similares con toggles.

 

Además las Feature toggles nos "regalan" un rollback sencillo: si una feature no funciona podemos desactivarla al momento.

 

Confianza


La confianza es algo importante para mi, siempre digo que quiero dormir por las noches. Con Feature toggles, lo normal es que tengas un único entorno productivo, por lo que cuando despliegas una release, esta va a todos los usuarios, aunque para algunos haya features desactivadas.

 

Si una release es "mala", a veces eso pasa :-(, y su problema no está tras una feature toggle, todos los usuarios lo sufrirán.

 

Sin embargo, con Deployment rings, solo los usuarios del primer anillo "sufrirían" esa "mala" release. 

 

Habilidades del equipo y aspectos organizativos

 

Diría que la opción de las Feature toggles es más cercana al desarrollo, mientras que los Deployment rings están más cerca de la infraestructura. Las habilidades de tu equipo o la organización de tu empresa pueden determinar la decisión.


¿Podemos usar ámbas opciones simultaneamente?

 

Claro, y en algunos casos será la opción más acertada :-)

 

Continuaré con estos temas en otros posts, espero que sean de interés.


Actualización:


Me indica Vicenç García que en Uber han hecho su propia herramienta para manejar esa deuda asociada a las Feature flags. ¡Gracias!


Introducing Piranha: An Open Source Tool to Automatically Delete Stale Code - Uber Engineering Blog