Creado: Flujo de trabajo con Git en Gitlab y GitHub authored by Santiago Martinez's avatar Santiago Martinez
# Flujo de trabajo con Git en Gitlab y GitHub
El objetivo de esta entrada es condensar en un solo documento, el flujo de trabajo adoptado por el equipo *DevOps* para el desarrollo y gestión de [`config`](https://git.interior.edu.uy/adminsys/config), el proyecto de [*infraestrcutura como código*](https://en.wikipedia.org/wiki/Infrastructure_as_code) de las Unidades Informáticas de la UdelaR en el Interior.
# Tabla de contenidos:
* [Git. Ramas y trabajo en equipo](#git-ramas-y-trabajo-en-equipo)
* [Flujos de trabajo estándar con Git](#flujos-de-trabajo-estándar-con-git)
* [¿Cómo implementamos *feature branch*?](#cómo-implementamos-feature-branch)
* [Integración con GitLab](#integración-con-gitlab)
* [GitLab flow](#gitlab-flow)
* [Nuestra manera](#nosotros-seguimos-estas-etapas-a-nuestra-manera)
* [¿Y en GitHub?](#y-en-github)
* [Dos gotas de agua](#dos-gotas-de-agua)
* [Fuentes y lecturas recomendadas](#fuentes-y-lecturas-recomendadas)
* [Pasando en limpio](#pasando-en-limpio)
## Git. Ramas y trabajo en equipo
Para gestionar el versionado de código y el trabajo colaborativo, utilizamos [Git](https://git-scm.com/). Una herramienta fundamental de este sistema es la disponibilidad de ramas. Con ellas podemos desarrollar en paralelo y aisladamente, las diferentes características que se van necesitando en el transcurso del proyecto.
Cuando el trabajo en una de estas ramas está finalizado, simplemente se fusiona dicha rama en la principal. Iterando sobre este proceso, se avanza rápida e incrementalmente sobre el proyecto; pero siempre manteniendo una versión madura y funcional, coloquialmente la rama estable o *master*.
Para un desarollador es relativamente sencillo saber en que rama estuvo trabajando cada fix o característica concreta. Pero el trabajo se da en equipo, ¿qué sucede, por ejemplo, cuando son varios los desarrolladores trabajando sobre la misma incidencia?
Sucede que se torna necesario acordar un criterio y flujo común para gestionar y ramificar el desarrollo. Lo mas deseable siempre es aprovechar la experiencia de la comunidad, adoptando un estándar popular, y en caso de ser necesario, adaptarlo a las necesidades particulares.
## Flujos de trabajo estándar con Git
Por el tipo de proyecto que nos atañe y por lo reducida cantidad de miembros del equipo, adoptamos es el estándar denominado [***feature branch***](https://www.atlassian.com/git/tutorials/comparing-workflows/feature-branch-workflow), una versión simplificada de [*Gitflow*](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow), el más popular en estos tiempos.
### *Feature branch workflow*
**La idea central detrás del flujo *feature branch*, es que el desarrollo de cualquier característica (*feature ~ característica*) debe tener lugar en una rama dedicada, en lugar de la rama *master*.**
Esta encapsulación facilita que múltiples desarrolladores **trabajen en una característica particular sin perturbar la base de código principal. También significa que la rama *master* nunca contendrá código intermedio o roto,** lo cual es una ventaja fundamental en entornos de integración continua.
Desarrollar las características encapsuladas en ramas, tiene el interés implícito de **aprovechar las herramientas de *merge/pull requests*** (en adelante *solicitudes de fusión*) que ofrecen GitLab y GitHub.
Las solicitudes de fusión son una forma muy práctica y útil de iniciar discusiones grupales en torno al trabajo realizado en una rama por uno o mas miembros. Permiten mantener un registro de todo el intercambio realizado como "línea del tiempo", facilitando referenciar código y enviando notificaciónes a los participantes correspondientes.
Le dan a todo el equipo la oportunidad de **validar y aprobar una nueva característica o fix antes de ser integrado a la base de código principal**, la rama *master*. Al mismo tiempo que son extremadamente útiles para solicitar ayuda o sugerencias a los compañeros.
## ¿Cómo implementamos *feature branch*?
### Integración con GitLab
El servidor empleado para hospedar el repositorio remoto del proyecto `config` es una instancia propia de [GitLab CE](https://about.gitlab.com/install/ce-or-ee), disponible en [git.interior.edu.uy](https://git.interior.edu.uy).
Este servicio se relaciona e integra profundamente al flujo de trabajo utilizado. No solo permite alojar un repositorio Git, sino que brinda un sinfín de herramientas en relación a la gestión de código, incidecias, etiquetas, documentación, e integración continua.
Estas herramientas estás diseñadas y orientadas a utilzar [*GitLab workflow*](https://about.gitlab.com/solutions/gitlab-flow/), una implementación vitaminada de *feature branch workflow*.
#### GitLab flow
El objetivo de este flujo es ayudar a los equipos a trabajar de manera cohesiva y efectiva desde la etapa de planeación hasta la puesta en producción.
En el siguiente diagrama se ilustran las etapas que componen el ciclo propuesto por GitLab:
---
#### Nosotros seguimos estas etapas, a nuestra manera:
* **IDEA:** cada nueva propuesta comienza con una idea, que generalmente surge en una conversación o chat.
* **ISSUE:** crear un *issue* para ella, la forma más efectiva de discutir una idea. Los miembros del equipo pueden ayudar a pulirla y mejorarla.
* **PLAN**: una vez que la discusión de implementación llega a un acuerdo, es hora de codear. Primero, se debe priorizar y organizar el flujo de trabajo. Para esto, es importante utilizar los [labels](https://docs.gitlab.com/ce/user/project/labels.html) e [issue boards](https://about.gitlab.com/stages-devops-lifecycle/issueboard/).
* **CÓDIGO:** ahora está todo listo para implementar el fix o feature. Para ello se deberá crear una nueva rama desde GitLab.
**Al hacerlo desde GitLab**, se asegurará y facilitará hacerlo del modo correcto:
* la rama se llamará igual al *issue*, prefijada por su ID
* partirá **siempre** desde la rama principal (*master*) actualizada
* se abrirá al mismo tiempo un *merge request* en estado *WIP* (*work in progress*) que resuelve el issue
* **COMMITS**: a medida que se van consiguiendo avances, es útil crear nuevos *commits* e irlos subiendo a la rama correspondiente. De este modo se va contando con versiones intermedias que pueden ser comentadas en el *issue*. A su vez, es un buen momento para hacer un *merge* desde *master* de modo de no distanciarse mucho del código en producción e ir resolviendo posibles conflictos paulatinamente.
* **REVISIÓN:** una vez damos por finalizada la implementación, con el código debidamente probado, pasamos la posta a un compañero para que realice la revisión y posterior fusión a *master*, es decir concluya la solicitud de fusión.
El procedimiento consistirá en localizar el *merge requests* creado junto a el issue para:
* asignarlo a un compañero que de preferencia no haya particiado activamente de la implementación
* agregar los comentarios que se consideren útiles para quién va a atender la solicitud
* retirar el prefijo *WIP* del *merge requests*, para indicar que el desarrollo se dió por finalizado y ya se puede iniciar el proceso de revisión y fusión
La revisión será conluída por el miembro del equipo asigando, quien antes de concretar la fusión a la rama principal deberá:
* probar el código por completo en un entorno de pruebas seguro
* asegurar que se satisfacen las necesidades planteadas en el issue
* analizar el código en busca de posibles errores, malas prácticas y vulnerabilidades
**Cualquier detalle que se aprecie deberá ser registrado como comentario en el *merge request*, solicitando al responsable de la implementación las correcciones pertinentes para iniciar nuevamente el proceso de revisión.**
Concluída la fusión, se deberá marcar como cerrados el *issue* y el *merge requests*
* **FEEDBACK:** de la puesta en producción pueden surgir ciertos detalles a pulir. Muchos de éstos es útil dejarlos documentados en el mismo *issue*. Aunque puedan no ameritar la reapertura, serán útiles para consulta futura.
El lector atento habrá notado que "nuestra manera" de *GitLab flow* solo difiere de la original en la (no) utilización de [CI/CD](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/). La intención es integrar esta etapa tan pronto sea posible. Espérelo en el asiento que considere más cómodo.
### ¿Y en GitHub?
Por tratarse de un proyecto que sigue las [buenas prácticas Ansible](https://docs.ansible.com/ansible/latest/user_guide/playbooks_best_practices.html#best-practices), `config` cuenta con de numerosos proyectos "satélite". Éstos proyectos corresponden a [*roles*](https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html#playbooks-reuse-roles), paquetes o módulos que se encargan de resolver una tarea concreta de forma genérica, característica que los hace ideales para compartir con la comunidad.
Varios de los roles utilizados, son precisamente de terceras partes, pero muchos otros son desarrollos propios. [Ansible brinda una plataforma](https://galaxy.ansible.com) para facilitar la publicación e intercambio de *roles*, que se integra con GitHub como repositorio de código.
Dado que nuestro objetivo es compartir todo lo posible, los desarrollos de *roles* propios, se encuentran versionados en [repositorios independietes de GitHub](https://github.com/UdelaRInterior) en lugar de el mismo que `config`; de modo que sea posible publicarlos en nuestro espacio en la [galaxia](https://galaxy.ansible.com/udelarinterior).
Al mismo tiempo mantenemos muchos *forks* de roles/repositorios de terceros, para contribuir en su desarrollo.
#### Dos gotas de agua
Si bien las herramientas que brindan GitLab y GitHub no son idénticas, son extremadamente similares; muchas veces sólo difieren en el nombre que se les da. Por esta razón, aplicamos el mismo flujo de trabajo que en GitLab.
En GitHub también tenemos a *issues*, *pull requests* (idénticos a los *merge requests*), posibilidad de asiganarles *labels*, miembros, notificaciones, etc.
**La mayor diferencia a destacar** es que en GitHub no tenemos la facilidad de crear una rama y una solicitud de fusión en estado *WIP* (no existe concepto equivalente) a partir de un *issue*. Tocará hacerlo manualmente, siempre respetando el estándar acordado, principalmente con el nombre de la rama.
Así como hay desventajas, también ventajas. En GitHub contamos con características muy útiles al momento de realizar revisiones y fusiones. En las solicitudes de fusión (*pull requests*), es posible asignar a un miembro específicamente para la revisión y otro para la fusión. Aquí las revisiones son un [feature completo](https://github.com/features/code-review/), con una dinámica más rica y guiada al momento de mantener discusiones sobre el código.
# Pasando en limpio
Expuestos ya los fundamentos, lo que importa que te lleves de aquí y mantengas siempre presente es:
* comenzar **siempre abriendo una *issue***, para que el intercambio y comentarios del equipo sobre el plan de implementación quede registrado
* trabajar **siempre en una rama idependiente** y específica para cada *issue*, con la solicitud de fusión abierta desde el primer momento en estado *WIP*
* **nunca desarrollar o trabajar sobre la rama *master***. La única excepción a esta regla son actualizaciones puntuales a features ya probados, [como la gestión de las zonas DNS](manejo-de-zonas-con-ansible)
* luego de dar por finalizada la implementación de un feature, **asignar la solicitud de fusión a un compañero** y retirar el *WIP* para que proceda a realizar la revisión
* **ser detallado y cuidadoso al momento de realizar revisiones**. Cualquier aspecto mejorable debe ser registrando como comentario en la solicitud de fusión o en el *commit* correspondiente, solicitando al autor su corrección para poder continuar con la revisión
> #### Fuentes: (y lecturas recomendadas)
>* [Feature Branch Workflow](https://www.atlassian.com/git/tutorials/comparing-workflows/feature-branch-workflow)
>* [A successful Git branching model](https://nvie.com/posts/a-successful-git-branching-model/)
>* [Gitflow Workflow](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow)
>* [GitLab Workflow: An Overview](https://about.gitlab.com/blog/2016/10/25/gitlab-workflow-an-overview/)
>* [GitLab flow](https://about.gitlab.com/solutions/gitlab-flow/)
>* [Pull requests and Gitflow](https://blog.axosoft.com/pull-requests-gitflow/)