# Versionamiento de código fuente

Para el sistema de versionamiento de software se deberán cumplir las siguientes reglas:

* Todos los proyectos nuevos deberán funcionar con el sistema de control de versiones *[Git](https://en.wikipedia.org/wiki/Git)*.
* No se deberán versionar archivos de más de 5 MB.
* Evitar versionar archivos binarios.

## Repositorios

Todos los repositorios asociados a herramientas, plataformas, procesos y demás temas relacionados deben pertenecer a la organización [Dirección de Conocimiento](https://github.com/PEM-Humboldt). La creación de repositorios está restringida a los propietarios de la organización. En caso de que a un investigador se le asigne la creación de un repositorio, obtendrá permisos temporales y deberá tener en cuenta lo siguiente:

* Asignar el repositorio a un [equipo de trabajo](https://github.com/orgs/PEM-Humboldt/teams). El equipo le será indicado en la tarea.
* Añadir los siguientes archivos al repositorio:
  * **LICENSE:** Usar la licencia MIT, a menos que se le indique otra.
  * **README.md:** Añadir información del proyecto. Si se desconoce, dejar el archivo en blanco
  * **.gitignore:** Usar una plantilla para el lenguaje que se vaya a utilizar. Si se desconoce, dejar el archivo en blanco.
  * **.gitattributes:** Usar una plantilla para el lenguaje que se vaya a utilizar. Si se desconoce, dejar el archivo en blanco.
* Crear la rama *develop* a partir de la rama *main*.
* Proteger ambas ramas:
  * No permitir *push* forzados
  * Requerir revisiones sobre los *PR*
  * Aplicar las reglas para los administradores también
* Poner la rama *develop* como rama por defecto

**NOTA:** Puede construir fácilmente archivos *gitignore* y *gitattributes* con las herramientas web [*gitignore.io*](http://gitignore.io) y [*gitattributes.io*](http://gitattributes.io).

## *Git flow*

### Commits

Se recomienda realizar commits con pocos cambios y con nombres cortos y concretos. Todos los commits deberán escribirse en Inglés.

Condiciones en los commits:

* Cada commit debe ser funcional. Es decir, al hacer checkout a un commit específico la aplicación debe funcionar sin errores de código.
* Dejar al final, o incluso en una rama aparte optimizaciones y otros ajustes que se encuentren necesarios durante el desarrollo de la tarea.
* Cuando se genera la documentación en el mismo repositorio, por ejemplo con *APIDoc*, se debe generar en una rama aparte, cuyo *PR* irá a la rama principal de la tarea.
* Deben ser escritos de tal forma que complementen la frase: *If applied, this commit will*…
* Cuando un mensaje sea muy grande, debe dividirse en varias líneas y la primera debe ser el “asunto” del commit, debe separarse por una línea en blanco del resto del commit, y el resto del commit puede ser una descripción o una lista de puntos para explicar más detalles.

### *Pull Requests* y *Merge Requests* (*PRs* y *MRs*)

* Antes de crear un *PR* (*Pull Request*) o *MR* (*Merge Requests*), se debe comprobar la funcionalidad del proyecto y los posibles eventos o errores que se hayan ejecutado en la plataforma de desarrollo (*GitHub*, *GitLab*) al ejecutar el comando *push*. En caso de existir errores, se deben solucionar antes de crear el *PR*.

  **Nota:** Para el caso de *GitHub*, se recomienda ejecutar las acciones de *github actions* de manera local. Para eso puede usar [act](https://github.com/nektos/act) (vea [aquí](https://medium.com/@debasishkumardas5/running-github-actions-locally-a-complete-guide-for-windows-mac-and-linux-users-34c45999c7cd) un instructivo).

* Al crear un *PR*, se debe seleccionar la rama que se trabajó el destino dependerá del tipo de desarrollo que se esté realizando (*feature*, *release* o *hotfix*). Recuerde que el orden de estas ramas está invertido en GitLab (para los *MR*)
* En caso de haber conflictos, el desarrollador que crea el *PR* debe resolverlos.
* Siempre se deben asignar revisores al *PR*.

#### Consideraciones
En caso de haber más de 2 revisores en el *PR*, se debe tener en cuenta:

* En casi todos los repositorios es suficiente con que uno lo apruebe. Pero la cantidad de aprobaciones necesarias es determinada por la sensibilidad de la tarea.
* Si un revisor solicita cambios, esa misma persona debe aprobar después.
* Más de un revisor puede solicitar cambios. Luego, se deberá tener la aprobación de todos los que hayan solicitado cambios.

### Revisores

Los revisores deben verificar en cada *PR* los siguientes puntos:

* Un correcto funcionamiento del proyecto
* Que la tarea, los criterios de aceptación y consideraciones se estén cumpliendo. Este paso se puede evitar en algunos casos, pero eso será mencionado en la tarea.
* No debe haber código comentado.
* No debe haber impresiones a consola (ejemplo: *console.log*, *print*, *p*, *system.out.println*)
* El archivo *readme* debe estar actualizado en caso de ser necesario. Por ejemplo, si se introducen o cambian variables de configuración. (Como regla general, el archivo *readme* siempre debe estar al día).
* El código ha sido documentado de acuerdo a las prácticas del repositorio / proyecto.
* Los nombres de las funciones y variables son claros de acuerdo a su uso.
* No hay código sin usar (variables, funciones, clases, sentencias sueltas, etc).
* El código en general es entendible y lo suficientemente óptimo.
  * Se debe buscar un balance entre optimización (entiéndase como evitar redundancias, repeticiones, estructuras de datos adecuadas, etc) y legibilidad del código.
  * Para el caso de JavaScript e implementaciones asíncronas prestar especial atención a las condiciones de carrera.
* Si el *PR* incluye una nueva dependencia en el proyecto, hacer una breve investigación sobre la dependencia para verificar que no tenga problemas de seguridad, que la actualicen con cierta frecuencia y que efectivamente sea necesaria.

### Ramas

El nombre de una rama debe tener el nombre del usuario del instituto, un símbolo de barra o *slash* (“/”) y el identificador de la tarea a resolver. Por ejemplo: *pperez/LIB-01*, *pgonzalez/LIB-042*

Una tarea puede ser de tipo *feature*, lo cual implica que se lleva a desarrollo (rama *develop*) o de tipo *hotfix*, la cual se lleva tanto a producción (rama *master* o *main*) como a desarrollo (rama *develop*). El flujo de trabajo con estas ramas tienen cosas en común, pero también sus diferencias.

Adicionalmente están las ramas *release*, que por lo regular tendrán una tarea asociada, pero es principalmente para marcar la dedicación en un sprint determinado y actualizar la documentación en otras ubicaciones.

#### Rama *Feature*

A continuación se presenta una guía del flujo de una rama tipo *feature*. Aquí se consideran tanto los pasos y recomendaciones para el encargado de hacer la tarea, como para los revisores.

![Manejo de ramas tipo "feature"](/resources/diagrams/git-flow/branches-feature.drawio.png)

#### Rama *Release*

A continuación se presenta una guía del flujo de una rama tipo *release*. Aquí se consideran tanto los pasos y recomendaciones para el encargado de hacer el lanzamiento, como para los revisores.

![Manejo de ramas tipo "release"](/resources/diagrams/git-flow/branches-release.drawio.png)

#### Rama *Hotfix*

Las tareas de estas ramas son para corregir algo urgente que no da tiempo de esperar a un lanzamiento.

A continuación se presenta una guía del flujo de una rama tipo *hotfix*. Aquí se consideran tanto los pasos y recomendaciones para el encargado de hacer el ajuste, como para los revisores.

![Manejo de ramas tipo "hotfix"](../../../resources/diagrams/git-flow/branches-hotfix.drawio.svg)

### Lanzamientos y etiquetas (Releases, tags)

Al crear un lanzamiento, se debe tener en cuenta lo siguiente:

1. Seleccionar la rama *main*/*master* para crear el lanzamiento
2. Asignar la etiqueta de la forma: **\<\#1\>.\<\#2\>.\<\#3\>** (ver [Versionamiento semántico](semantic-versioning.md))
3. Asignar el título de la versión de la forma: **\<\#1\>.\<\#2\>.\<\#3\>**
4. En la descripción del lanzamiento, redactar los cambios de la nueva versión teniendo en cuenta los siguiente:
   1. No especificar cada commit ni cada tarea, solo los cambios en funcionalidades completas.
   2. No detallar cambios técnicos. Por ejemplo, solo “*dependency update*” en lugar de listar todas las dependencias que se cambiaron

---
* volver al [inicio](/README.md)
* volver a las [normas de desarrollo](/docs/development-rules/README.md)
