#!/bin/bash # Analyze commits since last release and suggest next version number # # Usage: # ./scripts/suggest-version [--from TAG] # # Examples: # ./scripts/suggest-version # ./scripts/suggest-version --from v0.2.0 set -e SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "${SCRIPT_DIR}/.." # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' BOLD='\033[1m' NC='\033[0m' # Parse arguments FROM_TAG="${2:-}" # Get current version from manifest.json MANIFEST="custom_components/tibber_prices/manifest.json" if [[ ! -f "$MANIFEST" ]]; then echo -e "${RED}Error: Manifest file not found: $MANIFEST${NC}" exit 1 fi # Require jq for JSON parsing if ! command -v jq >/dev/null 2>&1; then echo -e "${RED}Error: jq is not installed${NC}" echo "Please install jq: apt-get install jq (or brew install jq)" exit 1 fi 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 echo -e "${RED}Error: No version tags found${NC}" exit 1 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" echo -e "${YELLOW}Note: manifest.json version ${MANIFEST_VERSION} already tagged as ${MANIFEST_TAG}${NC}" echo "" fi echo -e "${BOLD}Analyzing commits since $FROM_TAG${NC}" echo "" # Parse current version (from the tag we're analyzing from) CURRENT_VERSION="${FROM_TAG#v}" MAJOR=$(echo "$CURRENT_VERSION" | cut -d. -f1) MINOR=$(echo "$CURRENT_VERSION" | cut -d. -f2) PATCH=$(echo "$CURRENT_VERSION" | cut -d. -f3) echo "Current released version: v${MAJOR}.${MINOR}.${PATCH}" if [[ "$MANIFEST_VERSION" != "$CURRENT_VERSION" ]]; then echo -e "${YELLOW}Manifest.json version: ${MANIFEST_VERSION} (not yet tagged)${NC}" 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 echo -e "${YELLOW}No new commits since last release${NC}" # Check if manifest.json needs to be tagged if [[ "$MANIFEST_VERSION" != "$CURRENT_VERSION" ]]; then echo "" echo -e "${BLUE}Manifest.json has version ${MANIFEST_VERSION} but no tag exists yet.${NC}" 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 BREAKING_COUNT=$(echo "$COMMITS" | grep -c "^[^:]*!:" || true) FEAT_COUNT=$(echo "$COMMITS" | grep -cE "^feat(\(.+\))?:" || true) FIX_COUNT=$(echo "$COMMITS" | grep -cE "^fix(\(.+\))?:" || true) REFACTOR_COUNT=$(echo "$COMMITS" | grep -cE "^refactor(\(.+\))?:" || true) DOCS_COUNT=$(echo "$COMMITS" | grep -cE "^docs(\(.+\))?:" || true) OTHER_COUNT=$(echo "$COMMITS" | grep -vcE "^(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 -ci "BREAKING CHANGE:" || true) TOTAL_BREAKING=$((BREAKING_COUNT + BREAKING_IN_BODY)) echo -e "${BOLD}Commit Analysis:${NC}" echo "" if [ $TOTAL_BREAKING -gt 0 ]; then echo -e " ${RED}⚠ Breaking changes:${NC} $TOTAL_BREAKING" fi echo -e " ${GREEN}✨ New features:${NC} $FEAT_COUNT" echo -e " ${BLUE}🐛 Bug fixes:${NC} $FIX_COUNT" if [ $REFACTOR_COUNT -gt 0 ]; then echo -e " ${YELLOW}🔧 Refactorings:${NC} $REFACTOR_COUNT" fi if [ $DOCS_COUNT -gt 0 ]; then echo -e " 📚 Documentation: $DOCS_COUNT" fi if [ $OTHER_COUNT -gt 0 ]; then echo -e " 📦 Other: $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}" echo -e "${BOLD}${GREEN}Suggested Version: $SUGGESTED_VERSION${NC}" echo -e " Bump type: ${BUMP_TYPE}" echo -e " Reason: ${BUMP_REASON}" echo "" # Show alternative versions echo -e "${BOLD}Alternative Versions:${NC}" echo -e " ${YELLOW}MAJOR:${NC} v$((MAJOR + 1)).0.0 (if you want to release v1.0.0 or have breaking changes)" echo -e " ${GREEN}MINOR:${NC} v${MAJOR}.$((MINOR + 1)).0 (if adding features)" echo -e " ${BLUE}PATCH:${NC} v${MAJOR}.${MINOR}.$((PATCH + 1)) (if only fixes/docs)" echo "" # Show preview command echo -e "${BOLD}Preview Release Notes:${NC}" echo " ./scripts/generate-release-notes $FROM_TAG HEAD" echo "" echo -e "${BOLD}Create Release:${NC}" echo " ./scripts/prepare-release ${SUGGESTED_MAJOR}.${SUGGESTED_MINOR}.${SUGGESTED_PATCH}" echo "" # Show warning if breaking changes detected if [ $TOTAL_BREAKING -gt 0 ]; then echo -e "${RED}${BOLD}⚠ WARNING: Breaking changes detected!${NC}" echo -e "${RED}Make sure to document migration steps in release notes.${NC}" echo "" fi # Show note about pre-1.0 versioning if [ $MAJOR -eq 0 ]; then echo -e "${YELLOW}Note: Pre-1.0 versioning (0.x.y)${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