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.
Cristian Escalante
Última actualización: 28 de abril de 2025
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:
- Tener una API pública bien definida
- Haber probado tu software en entornos reales
- 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:
- alpha < beta < rc
- Los números se comparan numéricamente: alpha.1 < alpha.2
- 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:
- Analiza los mensajes de commit desde el último lanzamiento
- Determina la próxima versión basándose en los tipos de commit
- Genera notas de lanzamiento
- Crea etiquetas Git
- 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:
- Ser estricto con SemVer: Cualquier cambio incompatible debe incrementar la versión MAYOR
- Documentar claramente los cambios: Mantener un CHANGELOG detallado
- Proporcionar guías de migración: Para actualizaciones entre versiones MAYORES
- Mantener múltiples versiones: Dar soporte a versiones anteriores durante un período razonable
Aplicaciones
Para aplicaciones de usuario final:
- Versiones más frecuentes: Puedes incrementar la versión MENOR más frecuentemente
- Considerar versiones basadas en calendario: Especialmente para lanzamientos regulares
- Comunicar claramente los cambios: Notas de lanzamiento orientadas al usuario
Microservicios
Para arquitecturas de microservicios:
- Versionar APIs independientemente: Cada servicio puede tener su propia versión
- Usar versionado en la URL o encabezados:
/api/v1/recursos
oAccept: application/vnd.api+json;version=1
- 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):
- Marca la funcionalidad como obsoleta en una versión MENOR
- Proporciona alternativas y documentación
- 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:
- Agrupa múltiples cambios incompatibles
- Proporciona tiempo suficiente de aviso
- Crea documentación de migración detallada
- 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.