Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions scripts/next_release_version.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#!/usr/bin/env bash
# Compute the next release version for this repo.
#
# With existing vX.Y.Z tags — highest tag + 1 patch (e.g. v0.0.1 -> 0.0.2).
# Non-semver / pre-release tags (e.g. v0.1.0-alpha) are ignored.
# With no vX.Y.Z tags — base version from the first match of setup.py
# RELEASE_VERSION, pyproject.toml [project] version, a VERSION file, else 0.0.1.
#
# Usage:
# ./scripts/next_release_version.sh
# ./scripts/next_release_version.sh --verbose

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SOURCE_REPO="$(cd "$SCRIPT_DIR/.." && pwd)"

VERBOSE=0
while [[ $# -gt 0 ]]; do
case "$1" in
--verbose | -v)
VERBOSE=1
shift
;;
--help | -h)
sed -n '2,12p' "$0" | sed 's/^# \?//'
exit 0
;;
*)
echo "Unknown option: $1" >&2
exit 1
;;
esac
done

read_base_version() {
local v=""
if [[ -f "$SOURCE_REPO/setup.py" ]]; then
v="$(grep -E '^\s*RELEASE_VERSION\s*=' "$SOURCE_REPO/setup.py" | head -1 | sed -E 's/.*"([^"]+)".*/\1/')"
[[ "$v" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] && {
echo "$v"
return 0
}
fi
if [[ -f "$SOURCE_REPO/pyproject.toml" ]]; then
v="$(grep -E '^\s*version\s*=\s*"[0-9]' "$SOURCE_REPO/pyproject.toml" | head -1 | sed -E 's/.*"([^"]+)".*/\1/')"
[[ "$v" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] && {
echo "$v"
return 0
}
fi
if [[ -f "$SOURCE_REPO/VERSION" ]]; then
v="$(tr -d '[:space:]' < "$SOURCE_REPO/VERSION")"
[[ "$v" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] && {
echo "$v"
return 0
}
fi
echo "0.0.1"
}

increment_patch() {
local version="${1#v}"
local major minor patch
IFS=. read -r major minor patch <<< "$version"
echo "${major}.${minor}.$((patch + 1))"
}

highest_tag_version() {
local tag=""
cd "$SOURCE_REPO"
tag="$(git tag -l 'v[0-9]*' | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -1)"
if [[ -z "$tag" ]]; then
return 1
fi
echo "${tag#v}"
}

cd "$SOURCE_REPO"

if LAST_VERSION="$(highest_tag_version)"; then
VERSION="$(increment_patch "$LAST_VERSION")"
VERSION_SOURCE="git tag v${LAST_VERSION} + 1 patch"
else
VERSION="$(read_base_version)"
VERSION_SOURCE="base version (no release tags yet)"
fi

if [[ "$VERBOSE" -eq 1 ]]; then
echo "Version source: ${VERSION_SOURCE}"
if [[ -n "${LAST_VERSION:-}" ]]; then
echo "Last release tag: v${LAST_VERSION}"
else
echo "Last release tag: (none)"
fi
echo "Next version: ${VERSION}"
else
echo "$VERSION"
fi
56 changes: 41 additions & 15 deletions scripts/publish_release_tag.sh
Original file line number Diff line number Diff line change
@@ -1,38 +1,51 @@
#!/usr/bin/env bash
# Create and push a semver release tag. Pushing vX.Y.Z triggers publish-micropython-lib
# (sync micropython-lib, MIP index, and TestPyPI upload).
# Create and push a release tag for this repo. Same interface in every PyDevices repo.
#
# Version is the optional VERSION argument, else auto-computed by
# next_release_version.sh (highest vX.Y.Z tag + 1 patch). Pushing the tag
# triggers this repo's publish workflow.
#
# Usage:
# ./scripts/publish_release_tag.sh 0.0.5
# ./scripts/publish_release_tag.sh 0.0.5 --push
# ./scripts/publish_release_tag.sh # auto version; create tag
# ./scripts/publish_release_tag.sh --push # auto version; create + push
# ./scripts/publish_release_tag.sh 0.0.5 --push # explicit version; create + push
# ./scripts/publish_release_tag.sh --dry-run # preview only
#
# Preview the next version: ./scripts/next_release_version.sh --verbose

set -euo pipefail

DO_PUSH=0
DRY_RUN=0
VERSION=""

usage() {
cat <<'EOF'
Usage: ./scripts/publish_release_tag.sh VERSION [--push]
Usage: ./scripts/publish_release_tag.sh [VERSION] [--push] [--dry-run]

Create an annotated git tag vVERSION on the current commit.

--push Push the tag to origin (triggers the publish workflow)

Without --push, prints the git push command to run manually.
VERSION Optional semver X.Y.Z. When omitted, computed by
scripts/next_release_version.sh (highest tag + 1 patch).
--push Push the tag to origin (triggers this repo's publish workflow)
--dry-run Print the version that would be tagged; do not create a tag

Examples:
./scripts/publish_release_tag.sh --push
./scripts/publish_release_tag.sh 0.0.5 --push
git push origin v0.0.5
EOF
}

VERSION=""
while [[ $# -gt 0 ]]; do
case "$1" in
--push)
DO_PUSH=1
shift
;;
--dry-run)
DRY_RUN=1
shift
;;
--help | -h)
usage
exit 0
Expand All @@ -54,9 +67,13 @@ while [[ $# -gt 0 ]]; do
esac
done

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SOURCE_REPO="$(cd "$SCRIPT_DIR/.." && pwd)"

AUTO=0
if [[ -z "$VERSION" ]]; then
usage >&2
exit 1
AUTO=1
VERSION="$("$SCRIPT_DIR/next_release_version.sh")"
fi

VERSION="${VERSION#v}"
Expand All @@ -65,8 +82,6 @@ if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
exit 1
fi

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SOURCE_REPO="$(cd "$SCRIPT_DIR/.." && pwd)"
TAG="v$VERSION"

cd "$SOURCE_REPO"
Expand All @@ -81,12 +96,23 @@ if git rev-parse "$TAG" >/dev/null 2>&1; then
exit 1
fi

if [[ "$AUTO" -eq 1 ]]; then
"$SCRIPT_DIR/next_release_version.sh" --verbose
else
echo "Version: ${VERSION} (explicit)"
fi

if [[ "$DRY_RUN" -eq 1 ]]; then
echo "Dry run — would create tag $TAG on $(git rev-parse --short HEAD)"
exit 0
fi

git tag -a "$TAG" -m "Release $VERSION"
echo "Created annotated tag $TAG on $(git rev-parse --short HEAD)"

if [[ "$DO_PUSH" -eq 1 ]]; then
git push origin "$TAG"
echo "Pushed $TAG — publish-micropython-lib workflow should start shortly."
echo "Pushed $TAG — this repo's publish workflow should start shortly."
else
echo "Push to publish: git push origin $TAG"
fi
Loading