mirror of
https://github.com/jpawlowski/hass.tibber_prices.git
synced 2026-03-30 13:23:41 +00:00
feat(release): add semantic versioning workflow automation
Added intelligent version suggestion system based on Conventional Commits analysis to support proper semantic versioning. New scripts: - check-if-released: Verify if commit exists in any version tag - Helps decide if legacy migration code is needed - Shows guidance for breaking changes vs simple migrations - suggest-version: Analyze commits and suggest next version - Counts breaking changes, features, and bug fixes - Applies pre-1.0 rules: breaking→MINOR, feat→MINOR, fix→PATCH - Applies post-1.0 rules: breaking→MAJOR, feat→MINOR, fix→PATCH - Checks manifest.json and suggests alternatives (MAJOR/MINOR/PATCH) - Provides preview and release commands Updated scripts: - prepare-release: Now calls suggest-version when no argument provided - Shows suggested version before prompting - Maintains manual override capability Impact: Developers get intelligent version suggestions based on actual commit content, reducing versioning mistakes and following semver correctly.
This commit is contained in:
parent
7e57facf50
commit
ddc718aabd
3 changed files with 300 additions and 1 deletions
90
scripts/check-if-released
Executable file
90
scripts/check-if-released
Executable file
|
|
@ -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 <commit-hash>
|
||||||
|
# ./scripts/check-if-released <commit-hash> --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 <commit-hash> [--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
|
||||||
|
|
@ -10,7 +10,8 @@
|
||||||
# 5. Shows you what will be pushed (you decide when to push)
|
# 5. Shows you what will be pushed (you decide when to push)
|
||||||
#
|
#
|
||||||
# Usage:
|
# Usage:
|
||||||
# ./scripts/prepare-release VERSION
|
# ./scripts/prepare-release [VERSION]
|
||||||
|
# ./scripts/prepare-release --suggest
|
||||||
# ./scripts/prepare-release 0.3.0
|
# ./scripts/prepare-release 0.3.0
|
||||||
# ./scripts/prepare-release 1.0.0
|
# ./scripts/prepare-release 1.0.0
|
||||||
|
|
||||||
|
|
@ -21,10 +22,24 @@ RED='\033[0;31m'
|
||||||
GREEN='\033[0;32m'
|
GREEN='\033[0;32m'
|
||||||
YELLOW='\033[1;33m'
|
YELLOW='\033[1;33m'
|
||||||
BLUE='\033[0;34m'
|
BLUE='\033[0;34m'
|
||||||
|
BOLD='\033[1m'
|
||||||
NC='\033[0m' # No Color
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
cd "$(dirname "$0")/.."
|
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
|
# Check if we have uncommitted changes
|
||||||
if ! git diff-index --quiet HEAD --; then
|
if ! git diff-index --quiet HEAD --; then
|
||||||
echo -e "${RED}❌ Error: You have uncommitted changes.${NC}"
|
echo -e "${RED}❌ Error: You have uncommitted changes.${NC}"
|
||||||
|
|
|
||||||
194
scripts/suggest-version
Executable file
194
scripts/suggest-version
Executable file
|
|
@ -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
|
||||||
Loading…
Reference in a new issue