HDP115

Convención SemVer

Aprende a aplicar correctamente la convención de versionado semántico (SemVer) en tus proyectos, incluyendo casos especiales, extensiones y mejores prácticas para una gestión efectiva de versiones.

CE

Cristian Escalante

Última actualización: 28 de abril de 2025

git
control de versiones
desarrollo
buenas prácticas

Convención SemVer

En la lección anterior, aprendimos los fundamentos del versionado semántico (SemVer). Ahora profundizaremos en cómo aplicar correctamente esta convención en proyectos reales, explorando casos especiales, extensiones comunes y mejores prácticas para una gestión efectiva de versiones.

Especificación formal de SemVer

La convención SemVer está formalmente definida en semver.org y sigue este patrón:

MAYOR.MENOR.PARCHE[-pre-lanzamiento][+metadatos]

Donde:

  • MAYOR, MENOR y PARCHE son números enteros no negativos
  • pre-lanzamiento es una serie de identificadores separados por puntos
  • metadatos es información adicional que no afecta la precedencia

Casos especiales en SemVer

Versiones iniciales (0.y.z)

Durante el desarrollo inicial, cuando la API pública aún no es estable:

  • 0.1.0: Primera versión de desarrollo
  • 0.y.0: Nuevas características incompatibles
  • 0.y.z: Correcciones de errores

En esta fase, las reglas son más flexibles, ya que se entiende que la API puede cambiar rápidamente.

Versión 1.0.0

La versión 1.0.0 define la API pública inicial y marca el compromiso con la estabilidad. Antes de llegar a esta versión, deberías:

  1. Tener una API pública bien definida
  2. Haber probado tu software en entornos reales
  3. Estar preparado para mantener la compatibilidad hacia adelante

Versiones pre-lanzamiento

Las versiones pre-lanzamiento siguen un formato específico:

MAYOR.MENOR.PARCHE-[identificador].[número]

Ejemplos comunes:

  • 1.0.0-alpha.1: Primera versión alfa
  • 1.0.0-beta.2: Segunda versión beta
  • 1.0.0-rc.1: Primer candidato a lanzamiento

La precedencia se determina comparando cada identificador:

  1. alpha < beta < rc
  2. Los números se comparan numéricamente: alpha.1 < alpha.2
  3. Los identificadores solo con letras se comparan lexicográficamente

Metadatos de compilación

Los metadatos proporcionan información adicional pero no afectan la precedencia:

MAYOR.MENOR.PARCHE+[metadatos]

Ejemplos:

  • 1.0.0+20230415: Fecha de compilación
  • 1.0.0+sha.a1b2c3d: Hash del commit
  • 1.0.0-beta.1+exp.sha.5114f85: Versión beta con metadatos

Extensiones comunes de SemVer

Calendario de versiones (CalVer)

Algunas organizaciones combinan SemVer con versiones basadas en calendario:

AÑO.MES.NÚMERO

Ejemplos:

  • Ubuntu: 22.04 (abril de 2022)
  • Python: 3.10.4 (donde 3.10 es SemVer y el último dígito es incremental)

Versiones con sufijos de estado

Algunas organizaciones añaden sufijos para indicar el estado:

  • 1.0.0-LTS: Soporte a largo plazo
  • 2.1.0-stable: Versión estable
  • 3.0.0-nightly: Compilación nocturna

Implementación práctica de SemVer en Git

1. Etiquetas Git para versiones

Las etiquetas Git son la forma estándar de marcar versiones en un repositorio:

# Crear una etiqueta ligera
git tag v1.0.0

# Crear una etiqueta anotada (recomendada)
git tag -a v1.0.0 -m "Versión 1.0.0: Descripción del lanzamiento"

# Enviar etiquetas al repositorio remoto
git push origin v1.0.0
# o enviar todas las etiquetas
git push origin --tags

2. Convenciones de nomenclatura para etiquetas

Es común prefijar las etiquetas de versión con "v":

v1.0.0

Esto ayuda a distinguir las etiquetas de versión de otras etiquetas y es compatible con la mayoría de las herramientas.

3. Estructura de ramas para versiones

Una estructura común de ramas para gestionar versiones es:

  • main/master: Última versión estable
  • develop: Desarrollo activo
  • release/X.Y.Z: Preparación para lanzamiento
  • hotfix/X.Y.Z: Correcciones urgentes

4. Flujo de trabajo para lanzar una nueva versión

# 1. Crear una rama de lanzamiento
git checkout develop
git checkout -b release/1.0.0

# 2. Actualizar versión en archivos (package.json, etc.)
# ...

# 3. Commit de los cambios de versión
git add .
git commit -m "Prepara lanzamiento v1.0.0"

# 4. Fusionar con main/master
git checkout main
git merge --no-ff release/1.0.0

# 5. Crear etiqueta
git tag -a v1.0.0 -m "Versión 1.0.0"

# 6. Fusionar de vuelta a develop
git checkout develop
git merge --no-ff release/1.0.0

# 7. Eliminar rama de lanzamiento
git branch -d release/1.0.0

# 8. Enviar cambios y etiqueta
git push origin main develop v1.0.0

Automatización del versionado semántico

1. Conventional Commits

Conventional Commits es una especificación para mensajes de commit que facilita la automatización del versionado:

<tipo>[ámbito opcional]: <descripción>

[cuerpo opcional]

[nota de pie opcional]

Donde:

  • tipo: feat (característica), fix (corrección), docs, style, refactor, perf, test, chore
  • ámbito: componente afectado
  • descripción: resumen del cambio

Ejemplos:

feat(api): añade endpoint para autenticación OAuth

fix(ui): corrige overflow en dispositivos móviles

BREAKING CHANGE: cambia formato de respuesta API

2. Herramientas de automatización

semantic-release

semantic-release automatiza todo el flujo de trabajo de lanzamiento:

  1. Analiza los mensajes de commit desde el último lanzamiento
  2. Determina la próxima versión basándose en los tipos de commit
  3. Genera notas de lanzamiento
  4. Crea etiquetas Git
  5. Publica el paquete (npm, GitHub, etc.)

Configuración básica (.releaserc):

{
  "branches": ["main"],
  "plugins": [
    "@semantic-release/commit-analyzer",
    "@semantic-release/release-notes-generator",
    "@semantic-release/npm",
    "@semantic-release/github"
  ]
}

standard-version

standard-version es una alternativa más ligera:

# Instalar
npm install --save-dev standard-version

# Uso
npx standard-version

commitizen

commitizen ayuda a escribir mensajes de commit estandarizados:

# Instalar
npm install --save-dev commitizen cz-conventional-changelog

# Configurar
# En package.json:
"config": {
  "commitizen": {
    "path": "./node_modules/cz-conventional-changelog"
  }
}

# Uso
npx cz

Gestión de versiones en diferentes ecosistemas

JavaScript/Node.js (package.json)

{
  "name": "mi-paquete",
  "version": "1.0.0",
  "dependencies": {
    "dependencia1": "^1.0.0",
    "dependencia2": "~2.0.0"
  }
}

Comandos npm para gestionar versiones:

# Incrementar versión
npm version patch  # 1.0.0 -> 1.0.1
npm version minor  # 1.0.0 -> 1.1.0
npm version major  # 1.0.0 -> 2.0.0

# Versiones pre-lanzamiento
npm version prerelease --preid=alpha  # 1.0.0 -> 1.0.1-alpha.0

Python (setup.py/pyproject.toml)

# setup.py
setup(
    name="mi-paquete",
    version="1.0.0",
    # ...
)
# pyproject.toml
[tool.poetry]
name = "mi-paquete"
version = "1.0.0"

Java/Maven (pom.xml)

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.ejemplo</groupId>
    <artifactId>mi-proyecto</artifactId>
    <version>1.0.0</version>
</project>

Comandos Maven para gestionar versiones:

mvn versions:set -DnewVersion=1.1.0

.NET (*.csproj)

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <Version>1.0.0</Version>
  </PropertyGroup>
</Project>

Estrategias para diferentes tipos de proyectos

Bibliotecas y frameworks

Para bibliotecas que serán utilizadas como dependencias:

  1. Ser estricto con SemVer: Cualquier cambio incompatible debe incrementar la versión MAYOR
  2. Documentar claramente los cambios: Mantener un CHANGELOG detallado
  3. Proporcionar guías de migración: Para actualizaciones entre versiones MAYORES
  4. Mantener múltiples versiones: Dar soporte a versiones anteriores durante un período razonable

Aplicaciones

Para aplicaciones de usuario final:

  1. Versiones más frecuentes: Puedes incrementar la versión MENOR más frecuentemente
  2. Considerar versiones basadas en calendario: Especialmente para lanzamientos regulares
  3. Comunicar claramente los cambios: Notas de lanzamiento orientadas al usuario

Microservicios

Para arquitecturas de microservicios:

  1. Versionar APIs independientemente: Cada servicio puede tener su propia versión
  2. Usar versionado en la URL o encabezados: /api/v1/recursos o Accept: application/vnd.api+json;version=1
  3. Mantener compatibilidad hacia atrás: Especialmente importante para servicios internos

Mejores prácticas para SemVer

1. Documentación clara

Mantén un archivo CHANGELOG.md actualizado con cada versión, siguiendo un formato consistente como Keep a Changelog.

2. Pruebas de compatibilidad

Antes de decidir el incremento de versión, realiza pruebas para verificar la compatibilidad con versiones anteriores.

3. Comunicación con los usuarios

Comunica claramente a los usuarios qué tipo de cambios incluye cada versión y qué acciones deben tomar.

4. Deprecación antes de eliminación

Antes de eliminar funcionalidades (cambio MAYOR):

  1. Marca la funcionalidad como obsoleta en una versión MENOR
  2. Proporciona alternativas y documentación
  3. Mantén la funcionalidad obsoleta durante al menos una versión MAYOR

5. Planificación de versiones MAYORES

Las versiones MAYORES deben ser planificadas cuidadosamente:

  1. Agrupa múltiples cambios incompatibles
  2. Proporciona tiempo suficiente de aviso
  3. Crea documentación de migración detallada
  4. Considera períodos de soporte extendido para la versión anterior

6. Gestión de dependencias

Al especificar dependencias, usa rangos apropiados:

  • ^1.0.0: Aceptar actualizaciones MENORES y PARCHE (recomendado para la mayoría de casos)
  • ~1.0.0: Aceptar solo actualizaciones PARCHE (más conservador)
  • 1.0.0: Versión exacta (muy restrictivo)

7. Consistencia en el equipo

Asegúrate de que todo el equipo comprenda y siga las mismas convenciones de versionado.

Errores comunes y cómo evitarlos

1. Incrementar incorrectamente la versión

Problema: Incrementar la versión MAYOR para cambios menores o no incrementarla para cambios incompatibles.

Solución: Revisar cuidadosamente los cambios y su impacto en la API pública.

2. Olvidar actualizar la documentación

Problema: Lanzar una nueva versión sin actualizar el CHANGELOG o la documentación.

Solución: Automatizar la generación de notas de lanzamiento basadas en los commits.

3. Modificar versiones publicadas

Problema: Cambiar el contenido de una versión ya publicada.

Solución: Nunca modifiques una versión publicada; lanza una nueva versión con las correcciones.

4. Inconsistencia entre etiquetas y archivos

Problema: La versión en las etiquetas Git no coincide con la versión en los archivos del proyecto.

Solución: Automatizar el proceso de versionado para mantener la consistencia.

Conclusión

La convención SemVer proporciona un marco sólido para la gestión de versiones en proyectos de software. Al seguir estas reglas y mejores prácticas, puedes comunicar claramente los cambios en tu software y facilitar la vida de los desarrolladores que dependen de tu código.

Recuerda que el versionado semántico es principalmente una herramienta de comunicación. Su objetivo principal es gestionar las expectativas de los usuarios y reducir la "fricción de dependencias" en el ecosistema de software.

En la próxima lección, aprenderemos cómo etiquetar versiones en Git utilizando el comando git tag y cómo gestionar estas etiquetas de manera efectiva.

¿Qué es el versionado semántico?
Aprende los fundamentos del versionado semántico (SemVer), s...
Cómo etiquetar versiones en Git
Aprende a utilizar el sistema de etiquetas (tags) de Git par...
Referencias
Tom Preston-Werner. Semantic Versioning 2.0.0. https://semver.org/
Conventional Commits. Conventional Commits 1.0.0. https://www.conventionalcommits.org/en/v1.0.0/
Olivier Lacan. Keep a Changelog. https://keepachangelog.com/en/1.0.0/

Conceptos Básicos de HTML

Aprende los conceptos básicos de HTML

Conceptos Básicos de CSS

Aprende los conceptos básicos de CSS

Conceptos Básicos de JavaScript

Aprende los conceptos básicos de JavaScript

Conceptos Básicos SQL

Aprende los conceptos básicos de SQL

Conceptos Básicos de Python

Aprende los conceptos básicos de Python

Conceptos Básicos de UML

Aprende los conceptos básicos de UML

Refuerzo Academico de Herramientas de Productividad 2025