From 54cc741c1d3003942f41bd8c0a463d10f7b816d7 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Tue, 5 Aug 2025 18:53:01 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A8=20[devops]=20Scripts=20para=20la?= =?UTF-8?q?=20publicaci=C3=B3n=20de=20crates?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .cargo/cliff.toml | 67 +++++++++++++++++++++++++++++ .cargo/release.toml | 45 ++++++++++++++++++++ tools/changelog.sh | 101 ++++++++++++++++++++++++++++++++++++++++++++ tools/release.sh | 48 +++++++++++++++++++++ 4 files changed, 261 insertions(+) create mode 100644 .cargo/cliff.toml create mode 100644 .cargo/release.toml create mode 100755 tools/changelog.sh create mode 100755 tools/release.sh diff --git a/.cargo/cliff.toml b/.cargo/cliff.toml new file mode 100644 index 0000000..ff362c4 --- /dev/null +++ b/.cargo/cliff.toml @@ -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" }, +] diff --git a/.cargo/release.toml b/.cargo/release.toml new file mode 100644 index 0000000..9c07379 --- /dev/null +++ b/.cargo/release.toml @@ -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" +] diff --git a/tools/changelog.sh b/tools/changelog.sh new file mode 100755 index 0000000..19cbed9 --- /dev/null +++ b/tools/changelog.sh @@ -0,0 +1,101 @@ +#!/bin/bash +set -euo pipefail + +# ------------------------------------------------------------------------------ +# Script para generar el archivo de cambios del crate indicado. +# Uso: +# ./tools/changelog.sh [--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 [--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 diff --git a/tools/release.sh b/tools/release.sh new file mode 100755 index 0000000..f62993a --- /dev/null +++ b/tools/release.sh @@ -0,0 +1,48 @@ +#!/bin/bash +set -euo pipefail + +# ------------------------------------------------------------------------------ +# Script para publicar un crate individual del workspace con cargo-release. +# Uso: +# ./tools/release.sh [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 [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