#!/bin/bash # script/suggest-version: Suggest next semantic version based on commit analysis # # Analyzes conventional commits since last release and suggests appropriate # version bump (MAJOR.MINOR.PATCH) based on commit types. # # Usage: # ./scripts/release/suggest-version [--from TAG] # # Examples: # ./scripts/release/suggest-version # ./scripts/release/suggest-version --from v0.2.0 set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" cd "$SCRIPT_DIR/../.." # shellcheck source=scripts/.lib/output.sh source "$SCRIPT_DIR/../.lib/output.sh" # Parse arguments FROM_TAG="${2:-}" # Get current version from manifest.json MANIFEST="custom_components/tibber_prices/manifest.json" if [[ ! -f $MANIFEST ]]; then die "Manifest file not found: $MANIFEST" fi # Require jq for JSON parsing require_command "jq" "apt-get install jq (or brew install jq)" MANIFEST_VERSION=$(jq -r '.version' "$MANIFEST") MANIFEST_TAG="v${MANIFEST_VERSION}" # Get latest version tag if [[ -z $FROM_TAG ]]; then FROM_TAG=$(git tag -l 'v*.*.*' --sort=-version:refname | head -1) if [[ -z $FROM_TAG ]]; then die "No version tags found" fi fi # Check if manifest version already has a tag if git rev-parse "$MANIFEST_TAG" >/dev/null 2>&1; then # Manifest version is already tagged - analyze from that tag FROM_TAG="$MANIFEST_TAG" log_info "manifest.json version $MANIFEST_VERSION already tagged as $MANIFEST_TAG" echo "" fi log_header "Analyzing commits since $FROM_TAG" echo "" # Parse current version (from the tag we're analyzing from) parse_version() { local version="$1" if [[ $version =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)(b[0-9]+)?$ ]]; then echo "${BASH_REMATCH[1]} ${BASH_REMATCH[2]} ${BASH_REMATCH[3]} ${BASH_REMATCH[4]}" else die "Unsupported version format: $version\nExpected formats: X.Y.Z or X.Y.ZbN (e.g., 0.3.0, 1.0.0, 0.25.0b0)" fi } CURRENT_VERSION="${FROM_TAG#v}" read -r MAJOR MINOR PATCH PRERELEASE <<< "$(parse_version "$CURRENT_VERSION")" printf "Current released version: %bv%s.%s.%s%s%b\n" "$BOLD" "$MAJOR" "$MINOR" "$PATCH" "$PRERELEASE" "$NC" if [[ $MANIFEST_VERSION != "$CURRENT_VERSION" ]]; then log_warning "Manifest.json version: $MANIFEST_VERSION (not yet tagged)" fi echo "" # Analyze commits (exclude version bump commits) COMMITS=$(git log "$FROM_TAG"..HEAD --format="%s" --no-merges | grep -v "^chore(release):" || true) if [[ -z $COMMITS ]]; then log_warning "No new commits since last release" # Check if manifest.json needs to be tagged if [[ $MANIFEST_VERSION != "$CURRENT_VERSION" ]]; then echo "" log_info "Manifest.json has version $MANIFEST_VERSION but no tag exists yet." echo "Create tag with:" echo " git tag -a v${MANIFEST_VERSION} -m \"Release ${MANIFEST_VERSION}\"" echo " git push origin v${MANIFEST_VERSION}" fi exit 0 fi # Count commit types (using grep -c with || true to handle zero matches) BREAKING_COUNT=$(echo "$COMMITS" | grep -c "^[^:]*!:" || true) FEAT_COUNT=$(echo "$COMMITS" | grep -c -E "^feat(\(.+\))?:" || true) FIX_COUNT=$(echo "$COMMITS" | grep -c -E "^fix(\(.+\))?:" || true) REFACTOR_COUNT=$(echo "$COMMITS" | grep -c -E "^refactor(\(.+\))?:" || true) DOCS_COUNT=$(echo "$COMMITS" | grep -c -E "^docs(\(.+\))?:" || true) OTHER_COUNT=$(echo "$COMMITS" | grep -v -c -E "^(feat|fix|refactor|docs)(\(.+\))?:" || true) # Check for breaking changes in commit messages or Impact sections BREAKING_IN_BODY=$(git log "$FROM_TAG"..HEAD --format="%b" --no-merges | grep -c -i "BREAKING CHANGE:" || true) TOTAL_BREAKING=$((BREAKING_COUNT + BREAKING_IN_BODY)) printf "%bCommit Analysis:%b\n" "$BOLD" "$NC" echo "" if [ "$TOTAL_BREAKING" -gt 0 ]; then printf " %b⚠ Breaking changes:%b %s\n" "$RED" "$NC" "$TOTAL_BREAKING" fi printf " %b✨ New features:%b %s\n" "$GREEN" "$NC" "$FEAT_COUNT" printf " %b🐛 Bug fixes:%b %s\n" "$BLUE" "$NC" "$FIX_COUNT" if [ "$REFACTOR_COUNT" -gt 0 ]; then printf " %b🔧 Refactorings:%b %s\n" "$YELLOW" "$NC" "$REFACTOR_COUNT" fi if [ "$DOCS_COUNT" -gt 0 ]; then printf " 📚 Documentation: %s\n" "$DOCS_COUNT" fi if [ "$OTHER_COUNT" -gt 0 ]; then printf " 📦 Other: %s\n" "$OTHER_COUNT" fi echo "" # Determine version bump SUGGESTED_MAJOR=$MAJOR SUGGESTED_MINOR=$MINOR SUGGESTED_PATCH=$PATCH if [ "$TOTAL_BREAKING" -gt 0 ]; then # Before v1.0.0: Breaking changes bump minor # After v1.0.0: Breaking changes bump major if [ "$MAJOR" -eq 0 ]; then SUGGESTED_MINOR=$((MINOR + 1)) SUGGESTED_PATCH=0 BUMP_TYPE="MINOR (breaking changes in 0.x)" BUMP_REASON="Breaking changes detected (before v1.0.0 → bump minor)" else SUGGESTED_MAJOR=$((MAJOR + 1)) SUGGESTED_MINOR=0 SUGGESTED_PATCH=0 BUMP_TYPE="MAJOR (breaking)" BUMP_REASON="Breaking changes detected" fi elif [ "$FEAT_COUNT" -gt 0 ]; then SUGGESTED_MINOR=$((MINOR + 1)) SUGGESTED_PATCH=0 BUMP_TYPE="MINOR (features)" BUMP_REASON="New features added" elif [ "$FIX_COUNT" -gt 0 ]; then SUGGESTED_PATCH=$((PATCH + 1)) BUMP_TYPE="PATCH (fixes)" BUMP_REASON="Bug fixes only" else SUGGESTED_PATCH=$((PATCH + 1)) BUMP_TYPE="PATCH (other)" BUMP_REASON="Documentation/refactoring changes" fi SUGGESTED_VERSION="v${SUGGESTED_MAJOR}.${SUGGESTED_MINOR}.${SUGGESTED_PATCH}" printf "%b%bSuggested Version: %s%b\n" "$BOLD" "$GREEN" "$SUGGESTED_VERSION" "$NC" printf " Bump type: %s\n" "$BUMP_TYPE" printf " Reason: %s\n" "$BUMP_REASON" echo "" # Show alternative versions printf "%bAlternative Versions:%b\n" "$BOLD" "$NC" printf " %bMAJOR:%b v%s.0.0 (if you want to release v1.0.0 or have breaking changes)\n" "$YELLOW" "$NC" "$((MAJOR + 1))" printf " %bMINOR:%b v%s.%s.0 (if adding features)\n" "$GREEN" "$NC" "$MAJOR" "$((MINOR + 1))" printf " %bPATCH:%b v%s.%s.%s (if only fixes/docs)\n" "$BLUE" "$NC" "$MAJOR" "$MINOR" "$((PATCH + 1))" echo "" # Show preview command printf "%bPreview Release Notes:%b\n" "$BOLD" "$NC" echo " ./scripts/release/generate-notes $FROM_TAG HEAD" echo "" printf "%bCreate Release:%b\n" "$BOLD" "$NC" echo " ./scripts/release/prepare ${SUGGESTED_MAJOR}.${SUGGESTED_MINOR}.${SUGGESTED_PATCH}" echo "" # Show warning if breaking changes detected if [ "$TOTAL_BREAKING" -gt 0 ]; then printf "%b%b⚠ WARNING: Breaking changes detected!%b\n" "$RED" "$BOLD" "$NC" printf "%bMake sure to document migration steps in release notes.%b\n" "$RED" "$NC" echo "" fi # Show note about pre-1.0 versioning if [ "$MAJOR" -eq 0 ]; then printf "%bNote: Pre-1.0 versioning (0.x.y)%b\n" "$YELLOW" "$NC" echo " - Breaking changes bump MINOR (0.x.0)" echo " - Features bump MINOR (0.x.0)" echo " - Fixes bump PATCH (0.0.x)" echo " - After v1.0.0: Breaking changes bump MAJOR (x.0.0)" fi