diff --git a/scripts/check-if-released b/scripts/check-if-released new file mode 100755 index 0000000..cf3f9db --- /dev/null +++ b/scripts/check-if-released @@ -0,0 +1,90 @@ +#!/bin/bash +# Check if a commit or code change has been released (is contained in any version tag) +# +# Usage: +# ./scripts/check-if-released +# ./scripts/check-if-released --details +# +# Examples: +# ./scripts/check-if-released f4568be +# ./scripts/check-if-released HEAD~3 --details + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "${SCRIPT_DIR}/.." + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Check if commit hash provided +if [ -z "$1" ]; then + echo "Usage: $0 [--details]" + echo "" + echo "Examples:" + echo " $0 f4568be" + echo " $0 HEAD~3 --details" + exit 1 +fi + +COMMIT="$1" +DETAILS="${2:-}" + +# Validate commit exists +if ! git rev-parse --verify "$COMMIT" >/dev/null 2>&1; then + echo -e "${RED}Error: Commit '$COMMIT' not found${NC}" + exit 1 +fi + +# Get full commit hash +FULL_HASH=$(git rev-parse "$COMMIT") +SHORT_HASH=$(git rev-parse --short "$COMMIT") + +# Get commit info +COMMIT_SUBJECT=$(git log -1 --format="%s" "$COMMIT") +COMMIT_DATE=$(git log -1 --format="%ci" "$COMMIT") + +echo "Checking commit: $SHORT_HASH" +echo "Subject: $COMMIT_SUBJECT" +echo "Date: $COMMIT_DATE" +echo "" + +# Check if commit is in any version tag (v*.*.*) +TAGS=$(git tag --contains "$COMMIT" | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+' || true) + +if [ -z "$TAGS" ]; then + echo -e "${GREEN}✓ NOT RELEASED${NC}" + echo "This commit is not part of any version tag." + echo "" + echo -e "${YELLOW}→ No legacy migration needed for code introduced in this commit${NC}" + exit 0 +else + echo -e "${RED}✗ ALREADY RELEASED${NC}" + echo "This commit is included in the following version tags:" + echo "$TAGS" | sed 's/^/ - /' + echo "" + echo -e "${YELLOW}⚠ Breaking Change Decision:${NC}" + echo " 1. If migration is SIMPLE (e.g., .lower(), key rename) → Add it" + echo " 2. If migration is COMPLEX → Document in release notes instead" + echo " 3. Home Assistant style: Prefer breaking changes over code complexity" + echo "" + + if [ "$DETAILS" = "--details" ]; then + echo "" + echo "First release containing this commit:" + FIRST_TAG=$(echo "$TAGS" | head -1) + echo " Tag: $FIRST_TAG" + git log -1 --format=" Date: %ci" "$FIRST_TAG" + + echo "" + echo "Latest release:" + LATEST_TAG=$(git tag -l 'v*.*.*' --sort=-version:refname | head -1) + echo " Tag: $LATEST_TAG" + git log -1 --format=" Date: %ci" "$LATEST_TAG" + fi + + exit 1 +fi diff --git a/scripts/prepare-release b/scripts/prepare-release index 72d9cdf..3ef0401 100755 --- a/scripts/prepare-release +++ b/scripts/prepare-release @@ -10,7 +10,8 @@ # 5. Shows you what will be pushed (you decide when to push) # # Usage: -# ./scripts/prepare-release VERSION +# ./scripts/prepare-release [VERSION] +# ./scripts/prepare-release --suggest # ./scripts/prepare-release 0.3.0 # ./scripts/prepare-release 1.0.0 @@ -21,10 +22,24 @@ RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' +BOLD='\033[1m' NC='\033[0m' # No Color cd "$(dirname "$0")/.." +# Check if --suggest or no argument +if [[ "${1:-}" == "--suggest" ]] || [[ -z "${1:-}" ]]; then + ./scripts/suggest-version + + if [[ -z "${1:-}" ]]; then + echo "" + echo -e "${YELLOW}Provide version number as argument:${NC}" + echo " ./scripts/prepare-release X.Y.Z" + exit 0 + fi + exit 0 +fi + # Check if we have uncommitted changes if ! git diff-index --quiet HEAD --; then echo -e "${RED}❌ Error: You have uncommitted changes.${NC}" diff --git a/scripts/suggest-version b/scripts/suggest-version new file mode 100755 index 0000000..a2eaa8f --- /dev/null +++ b/scripts/suggest-version @@ -0,0 +1,194 @@ +#!/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