|
|
|
# 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/) |