🔨 [devops] Scripts para la publicación de crates

This commit is contained in:
Manuel Cillero 2025-08-05 18:53:01 +02:00
parent b4cbfc4775
commit 54cc741c1d
4 changed files with 261 additions and 0 deletions

67
.cargo/cliff.toml Normal file
View file

@ -0,0 +1,67 @@
# cliff.toml
[changelog]
header = """
# CHANGELOG
Este archivo documenta los cambios más relevantes realizados en cada versión. El formato está basado
en [Keep a Changelog](https://keepachangelog.com/es-ES/1.0.0/), y las versiones se numeran siguiendo
las reglas del [Versionado Semántico](https://semver.org/lang/es/).
Resume la evolución del proyecto para usuarios y colaboradores, destacando nuevas funcionalidades,
correcciones, mejoras durante el desarrollo o cambios en la documentación. Cambios menores o
internos pueden omitirse si no afectan al uso del proyecto.
"""
trim = true
render_always = true
body = """
{% if version %}
## {{ version | trim_start_matches(pat="v") }} ({{ timestamp | date(format="%Y-%m-%d") }})
{% else %}
## Pendiente de publicación
{% endif %}\
{% set base = "https://git.cillero.es/manuelcillero/pagetop" %}\
{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | upper_first }}
{% for commit in commits %}
{%- set msg = commit.message
| split(pat="\n")
| first
| replace(from="✨ ", to="")
| replace(from="🐛 ", to="")
| replace(from="⬆️ ", to="")
| replace(from="🚧 ", to="")
| replace(from="♻️ ", to="")
| replace(from="✏️ ", to="")
| replace(from="🏷️ ", to="")
| replace(from="🧑‍💻 ", to="")
| replace(from="🍱 ", to="")
| replace(from="📝 ", to="")
| replace(from="💡 ", to="")
-%}
{% set sha7 = commit.id | truncate(length=7, end="") %}
- {{ msg | trim }} ([{{ sha7 }}]({{ base }}/commit/{{ commit.id }}){% if commit.author.name != "Manuel Cillero" %} - {{ commit.author.name }}{% endif %})
{% endfor %}{% endfor %}
"""
[git]
conventional_commits = false
filter_unconventional = false
topo_order_commits = true
sort_commits = "oldest"
commit_parsers = [
{ message = "^✨", group = "Añadido" },
{ message = "^🐛", group = "Corregido" },
{ message = "^🚧", group = "Cambiado" },
{ message = "^♻️", group = "Cambiado" },
{ message = "^✏️", group = "Cambiado" },
{ message = "^🏷️", group = "Cambiado" },
{ message = "^🧑‍💻", group = "Cambiado" },
{ message = "^🍱", group = "Cambiado" },
{ message = "^⬆️", group = "Dependencias" },
{ message = "^📝", group = "Documentado" },
{ message = "^💡", group = "Documentado" },
{ message = "^.*", group = "Otros cambios" },
]

45
.cargo/release.toml Normal file
View file

@ -0,0 +1,45 @@
# release.toml
# Etiqueta por crate: `pagetop-macros-v0.2.0`
tag-prefix = "{{crate_name}}-v"
# Confirmaciones firmadas (no requeridas)
sign-commit = false
sign-tag = false
# Empuja etiquetas y commits
push = true
# Publica en crates.io (puedes desactivarlo para pruebas)
publish = true
# Actualiza todos los dependientes internos
update-dependencies = true
# Solo permite publicar estos crates (los que forman parte del workspace)
allow-branch = ["main"]
consolidate-commits = false
consolidate-pushes = true
# Mensaje personalizado para el commit de versión
pre-release-commit-message = "🔖 Prepara publicación de {{crate_name}} {{version}}"
[workspace]
# Lista de crates que se pueden publicar dentro del workspace
# Puedes añadir extensiones más adelante
allow-publish = [
"pagetop",
"pagetop-build",
"pagetop-macros"
]
# Opcional: ordena la publicación de dependencias internas
publish-order = [
"pagetop-build",
"pagetop-macros",
"pagetop"
]
pre-release-hook = [
"./tools/changelog.sh", "{{crate_name}}", "{{version}}", "--stage"
]

101
tools/changelog.sh Executable file
View file

@ -0,0 +1,101 @@
#!/bin/bash
set -euo pipefail
# ------------------------------------------------------------------------------
# Script para generar el archivo de cambios del crate indicado.
# Uso:
# ./tools/changelog.sh <crate> <version> [--stage]
# Ejemplo:
# ./tools/changelog.sh pagetop-macros 0.1.0 # Sólo genera archivo
# ./tools/changelog.sh pagetop 0.1.0 --stage # Prepara archivo para commit
# ------------------------------------------------------------------------------
# Configuración
CRATE="${1:-}"
VERSION="${2:-}"
STAGE="${3:-}"
CLIFF_CONFIG=".cargo/cliff.toml"
# Comprobaciones
if [[ -z "$CRATE" || -z "$VERSION" ]]; then
echo "Usage: $0 <crate> <version> [--stage]" >&2
exit 1
fi
# Dependencias
command -v git-cliff >/dev/null || {
echo "Error: git-cliff is not installed. Use: cargo install git-cliff"
exit 1
}
# Cambia al directorio del espacio
cd "$(dirname "$0")/.." || exit 1
# ------------------------------------------------------------------------------
# Determina ruta del archivo y ámbito de los archivos afectados para el crate
# ------------------------------------------------------------------------------
case "$CRATE" in
pagetop)
CHANGELOG_FILE="CHANGELOG.md"
PATH_FLAGS=(
--exclude-path "helpers/pagetop-macros/**/*"
--exclude-path "helpers/pagetop-build/**/*"
)
;;
pagetop-macros)
CHANGELOG_FILE="helpers/pagetop-macros/CHANGELOG.md"
PATH_FLAGS=(--include-path "helpers/pagetop-macros/**/*")
;;
pagetop-build)
CHANGELOG_FILE="helpers/pagetop-build/CHANGELOG.md"
PATH_FLAGS=(--include-path "helpers/pagetop-build/**/*")
;;
*)
echo "Error: unsupported crate '$CRATE'" >&2
exit 1
;;
esac
# ------------------------------------------------------------------------------
# Obtiene la última etiqueta del crate
# ------------------------------------------------------------------------------
LAST_TAG="$(git tag --list "${CRATE}-v*" --sort=-v:refname | head -n 1)"
if [[ -n "$LAST_TAG" ]]; then
echo "Generating CHANGELOG for '$CRATE' from last tag '$LAST_TAG'"
CLIFF_ARGS=(--unreleased --tag "$VERSION")
else
echo "Generating initial CHANGELOG for '$CRATE'"
CLIFF_ARGS=(--tag "$VERSION")
fi
# ------------------------------------------------------------------------------
# Genera el CHANGELOG para el crate correspondiente
# ------------------------------------------------------------------------------
git-cliff --config "$CLIFF_CONFIG" "${PATH_FLAGS[@]}" "${CLIFF_ARGS[@]}" -o "$CHANGELOG_FILE" -u
echo "CHANGELOG generated at '$CHANGELOG_FILE'"
# Pregunta por la revisión del archivo de cambios generado
read -p "Do you want to review the changelog before continuing? (y/n) " -n 1 -r || exit 1
echo
if [[ "$REPLY" =~ ^[Yy]$ ]]; then
${EDITOR:-nano} "$CHANGELOG_FILE"
fi
read -p "Do you want to proceed with the release of $CRATE? (y/n) " -n 1 -r || exit 1
echo
if [[ ! "$REPLY" =~ ^[Yy]$ ]]; then
echo "Aborting release process." >&2
exit 1
fi
# Si hay cambios y procede, añade al stage (cargo-release hará el commit)
if ! git diff --quiet -- "$CHANGELOG_FILE"; then
if [[ "$STAGE" == "--stage" ]]; then
git add "$CHANGELOG_FILE"
echo "Staged $CHANGELOG_FILE for commit"
else
echo "Changes detected in '$CHANGELOG_FILE', but not staged (no --stage flag)"
fi
else
echo "No changes in '$CHANGELOG_FILE', skipping staging"
fi

48
tools/release.sh Executable file
View file

@ -0,0 +1,48 @@
#!/bin/bash
set -euo pipefail
# ------------------------------------------------------------------------------
# Script para publicar un crate individual del workspace con cargo-release.
# Uso:
# ./tools/release.sh <crate> [patch|minor|major] [--execute]
# Ejemplos:
# ./tools/release.sh pagetop-macros patch # Dry run (por defecto)
# ./tools/release.sh pagetop minor --execute # Publicación real
# ------------------------------------------------------------------------------
# Configuración
CRATE="${1:-}"
LEVEL="${2:-patch}"
EXECUTE="${3:-}"
CONFIG=".cargo/release.toml"
# Comprobaciones
if [[ -z "$CRATE" ]]; then
echo "Usage: $0 <crate> [patch|minor|major] [--execute]"
exit 1
fi
if [[ ! "$LEVEL" =~ ^(patch|minor|major)$ ]]; then
echo "Error: invalid level '$LEVEL'. Use: patch, minor, or major"
exit 1
fi
# Dependencias
command -v cargo-release >/dev/null || {
echo "Error: cargo-release is not installed. Use: cargo install cargo-release"
exit 1
}
# Cambia al directorio del espacio
cd "$(dirname "$0")/.." || exit 1
# ------------------------------------------------------------------------------
# DRY-RUN (por defecto) o ejecución real con --execute
# ------------------------------------------------------------------------------
if [[ "$EXECUTE" != "--execute" ]]; then
echo "Running dry-run (default mode). Add --execute to publish"
CARGO_RELEASE_CONFIG="$CONFIG" cargo release --package "$CRATE" "$LEVEL" --dry-run
else
echo "Releasing $CRATE ($LEVEL)…"
CARGO_RELEASE_CONFIG="$CONFIG" cargo release --package "$CRATE" "$LEVEL" --execute
echo "Release completed."
fi