scripts/release_version.sh
Rama main · réplica de lectura del repositorio original.
#!/usr/bin/env bash
set -euo pipefail
# Application releases use YY.MM.N[-rc.K]; .agents/skills/release/SKILL.md says
# how N and K are chosen. Bare YY.MM is only an image tag that follows the newest
# stable of its month. Database migration sequences are separate.
parse_release_tag() {
local tag="$1"
if [[ ! "$tag" =~ ^([1-9][0-9]\.(0[1-9]|1[0-2]))\.(0|[1-9][0-9]*)(-rc\.([1-9][0-9]*))?$ ]]; then
return 1
fi
RELEASE_VERSION="$tag"
RELEASE_SERIES="${BASH_REMATCH[1]}"
RELEASE_IS_PRERELEASE=false
if [[ -n "${BASH_REMATCH[5]}" ]]; then
RELEASE_IS_PRERELEASE=true
fi
}
# development_version prints YY.MM.D-dev.<sha7> for HEAD from its committer date
# in UTC, matching internal/version. format-local honors TZ; plain format uses
# the commit's original zone.
development_version() {
local repo="$1" head month day sha version
head="$(TZ=UTC git -C "$repo" show -s --format='%cd %H' --date='format-local:%y.%m %d' HEAD)"
read -r month day sha <<<"$head"
version="$month.${day#0}"
if ! parse_release_tag "$version"; then
echo "Cannot derive a calendar version from HEAD" >&2
return 1
fi
printf '%s-dev.%s\n' "$version" "${sha:0:7}"
}
# previous_release_tag prints the newest stable release tag that is an ancestor
# of HEAD, excluding tags on HEAD itself. Legacy v0.31.x tags count because
# v0.31.0 is the fixed upgrade baseline.
previous_release_tag() {
local repo="$1" head_sha tag tag_sha
head_sha="$(git -C "$repo" rev-parse HEAD)"
# List calendar releases first: the legacy v prefix would otherwise sort ahead.
while IFS= read -r tag; do
if parse_release_tag "$tag"; then
[[ "$RELEASE_IS_PRERELEASE" == false ]] || continue
elif [[ ! "$tag" =~ ^v0\.31\.(0|[1-9][0-9]*)$ ]]; then
continue
fi
tag_sha="$(git -C "$repo" rev-list -n 1 "$tag")"
[[ "$tag_sha" != "$head_sha" ]] || continue
if git -C "$repo" merge-base --is-ancestor "$tag" HEAD; then
printf '%s\n' "$tag"
return
fi
done < <(
git -C "$repo" tag --list '[1-9][0-9].*' --sort=-version:refname
git -C "$repo" tag --list 'v0.31.*' --sort=-version:refname
)
echo 'No supported previous release found' >&2
return 1
}
previous_release_image() {
local tag
if ! tag="$(previous_release_tag "$1")"; then
echo 'Pass --previous-image' >&2
return 1
fi
printf 'neosmemo/memos:%s\n' "${tag#v}"
}
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
case "${1:-}" in
development-version)
development_version "${2:-.}"
exit
;;
previous-tag)
previous_release_tag "${2:?repository required}"
exit
;;
previous-image)
previous_release_image "${2:?repository required}"
exit
;;
esac
tag="${2:?release tag required}"
if ! parse_release_tag "$tag"; then
echo "Unsupported release tag format: $tag" >&2
exit 1
fi
case "${1:-}" in
version)
printf 'tag=%s\nversion=%s\nseries=%s\nis_prerelease=%s\n' \
"$tag" "$RELEASE_VERSION" "$RELEASE_SERIES" "$RELEASE_IS_PRERELEASE"
;;
image-tags)
printf '%s\n' "$RELEASE_VERSION"
if [[ "$RELEASE_IS_PRERELEASE" == false ]]; then
printf '%s\nstable\n' "$RELEASE_SERIES"
fi
;;
*) echo "Unknown release command: ${1:-}" >&2; exit 1 ;;
esac
fi