mirror of
https://github.com/jpawlowski/hass.tibber_prices.git
synced 2026-03-30 21:33:39 +00:00
Major restructuring of the scripts/ directory with consistent output
formatting, improved organization, and stricter error handling.
Breaking Changes:
- Updated development environment to Home Assistant 2025.7+
- Removed Python 3.12 compatibility (HA 2025.7+ requires Python 3.13)
- Updated all HA core requirements from 2025.7 requirement files
- Added new dependencies: python-multipart, uv (for faster package management)
- Updated GitHub Actions workflows to use Python 3.13
Changes:
- Created centralized output library (scripts/.lib/output.sh)
- Unified color codes and Unicode symbols
- Consistent formatting functions (log_header, log_success, log_error, etc.)
- Support for embedded formatting codes (${BOLD}, ${GREEN}, etc.)
- Reorganized into logical subdirectories:
- scripts/setup/ - Setup and maintenance scripts
- bootstrap: Install/update dependencies (used in CI/CD)
- setup: Full DevContainer setup (pyright, copilot, HACS)
- reset: Reset config/ directory to fresh state (NEW)
- sync-hacs: Sync HACS integrations
- scripts/release/ - Release management scripts
- prepare: Version bump and tagging
- suggest-version: Semantic version suggestion
- generate-notes: Release notes generation
- check-if-released: Check release status
- hassfest: Local integration validation
- Updated all scripts with:
- set -euo pipefail for stricter error handling
- Consistent SCRIPT_DIR pattern for reliable sourcing
- Professional output with colors and emojis
- Unified styling across all 17 scripts
- Removed redundant scripts:
- scripts/update (was just wrapper around bootstrap)
- scripts/json_schemas/ (moved to schemas/json/)
- Enhanced clean script:
- Improved artifact cleanup
- Better handling of accidental package installations
- Hints for reset and deep clean options
- New reset script features:
- Standard mode: Keep configuration.yaml
- Full mode (--full): Reset configuration.yaml from git
- Automatic re-setup after reset
- Updated documentation:
- AGENTS.md: Updated script references and workflow guidance
- docs/development/: Updated all references to new script structure
Impact: Development environment now requires Python 3.13 and Home Assistant
2025.7+. Developers get consistent, professional script output with better
error handling and logical organization. Single source of truth for styling
makes future updates trivial.
254 lines
10 KiB
YAML
254 lines
10 KiB
YAML
name: Generate Release Notes
|
|
|
|
on:
|
|
push:
|
|
tags:
|
|
- 'v*.*.*' # Triggers on version tags like v1.0.0, v2.1.3, etc.
|
|
workflow_dispatch:
|
|
inputs:
|
|
tag:
|
|
description: 'Tag version to release (e.g., v0.3.0)'
|
|
required: true
|
|
type: string
|
|
|
|
permissions:
|
|
contents: write # Needed to create/update releases and push commits
|
|
|
|
jobs:
|
|
# Note: We trust that validate.yml and lint.yml have already run on the
|
|
# main branch commit before the tag was created (either by prepare-release
|
|
# script or auto-tag workflow). This avoids duplicate workflow runs.
|
|
|
|
sync-manifest:
|
|
name: Sync manifest.json with tag version
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
updated: ${{ steps.update.outputs.updated }}
|
|
version: ${{ steps.tag.outputs.version }}
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v6.0.0
|
|
with:
|
|
fetch-depth: 0
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Extract version from tag
|
|
id: tag
|
|
run: |
|
|
TAG_VERSION="${GITHUB_REF#refs/tags/v}"
|
|
echo "version=$TAG_VERSION" >> $GITHUB_OUTPUT
|
|
echo "Tag version: v$TAG_VERSION"
|
|
|
|
- name: Check manifest.json version
|
|
id: manifest
|
|
run: |
|
|
MANIFEST_VERSION=$(grep -o '"version": "[^"]*"' custom_components/tibber_prices/manifest.json | cut -d'"' -f4)
|
|
echo "version=$MANIFEST_VERSION" >> $GITHUB_OUTPUT
|
|
echo "Manifest version: $MANIFEST_VERSION"
|
|
|
|
- name: Update manifest.json if needed
|
|
id: update
|
|
run: |
|
|
TAG_VERSION="${{ steps.tag.outputs.version }}"
|
|
MANIFEST_VERSION="${{ steps.manifest.outputs.version }}"
|
|
|
|
if [ "$TAG_VERSION" != "$MANIFEST_VERSION" ]; then
|
|
echo "::notice::Version mismatch detected - auto-syncing"
|
|
echo " Tag: v$TAG_VERSION"
|
|
echo " Manifest: $MANIFEST_VERSION"
|
|
|
|
# Update manifest.json
|
|
sed -i "s/\"version\": \".*\"/\"version\": \"$TAG_VERSION\"/" custom_components/tibber_prices/manifest.json
|
|
|
|
# Verify update
|
|
NEW_VERSION=$(grep -o '"version": "[^"]*"' custom_components/tibber_prices/manifest.json | cut -d'"' -f4)
|
|
if [ "$NEW_VERSION" = "$TAG_VERSION" ]; then
|
|
echo "✓ Successfully updated manifest.json to $TAG_VERSION"
|
|
echo "updated=true" >> $GITHUB_OUTPUT
|
|
else
|
|
echo "::error::Failed to update manifest.json"
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "✓ Versions match - no update needed"
|
|
echo "updated=false" >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
- name: Commit and push manifest.json update
|
|
if: steps.update.outputs.updated == 'true'
|
|
run: |
|
|
git config user.name "github-actions[bot]"
|
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
|
|
git add custom_components/tibber_prices/manifest.json
|
|
git commit -m "chore(release): sync manifest.json with tag v${{ steps.tag.outputs.version }}"
|
|
|
|
# Push to main branch
|
|
git push origin HEAD:main
|
|
|
|
release-notes:
|
|
name: Generate and publish release notes
|
|
runs-on: ubuntu-latest
|
|
needs: sync-manifest # Wait for manifest sync to complete
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v6.0.0
|
|
with:
|
|
fetch-depth: 0 # Fetch all history for git-cliff
|
|
ref: main # Use updated main branch if manifest was synced
|
|
|
|
- name: Get previous tag
|
|
id: previoustag
|
|
run: |
|
|
PREVIOUS_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
|
|
echo "previous_tag=${PREVIOUS_TAG}" >> $GITHUB_OUTPUT
|
|
echo "Previous tag: ${PREVIOUS_TAG}"
|
|
|
|
- name: Check version appropriateness
|
|
id: version_check
|
|
run: |
|
|
TAG_VERSION="${GITHUB_REF#refs/tags/v}"
|
|
PREV_TAG="${{ steps.previoustag.outputs.previous_tag }}"
|
|
|
|
if [ -z "$PREV_TAG" ]; then
|
|
echo "warning=" >> $GITHUB_OUTPUT
|
|
exit 0
|
|
fi
|
|
|
|
# Analyze commits between tags
|
|
COMMITS=$(git log ${PREV_TAG}..HEAD --format="%s" --no-merges)
|
|
BREAKING=$(echo "$COMMITS" | grep -cE "^[^:]+!:|^[^:]+: .+BREAKING CHANGE" || true)
|
|
FEAT=$(echo "$COMMITS" | grep -cE "^feat(\(.+\))?:" || true)
|
|
FIX=$(echo "$COMMITS" | grep -cE "^fix(\(.+\))?:" || true)
|
|
|
|
# Parse versions
|
|
PREV_VERSION="${PREV_TAG#v}"
|
|
IFS='.' read -r PREV_MAJOR PREV_MINOR PREV_PATCH <<< "$PREV_VERSION"
|
|
IFS='.' read -r MAJOR MINOR PATCH <<< "$TAG_VERSION"
|
|
|
|
WARNING=""
|
|
SUGGESTION=""
|
|
|
|
# Pre-1.0 version rules (0.x.y)
|
|
if [ "$MAJOR" -eq 0 ]; then
|
|
if [ $BREAKING -gt 0 ] && [ "$MINOR" = "$PREV_MINOR" ]; then
|
|
WARNING="⚠️ **Version Warning**: $BREAKING breaking change(s) detected, but only PATCH version bumped."
|
|
SUGGESTION="In pre-1.0 (0.x.y), breaking changes should bump MINOR version. Consider **v0.$((MINOR + 1)).0** instead of v$TAG_VERSION"
|
|
elif [ $FEAT -gt 0 ] && [ "$MINOR" = "$PREV_MINOR" ] && [ "$PATCH" != "$PREV_PATCH" ]; then
|
|
WARNING="⚠️ **Version Warning**: $FEAT new feature(s) detected, but only PATCH version bumped."
|
|
SUGGESTION="New features should bump MINOR version. Consider **v0.$((MINOR + 1)).0** instead of v$TAG_VERSION"
|
|
fi
|
|
else
|
|
# Post-1.0 version rules (x.y.z)
|
|
if [ $BREAKING -gt 0 ] && [ "$MAJOR" = "$PREV_MAJOR" ]; then
|
|
WARNING="⚠️ **Version Warning**: $BREAKING breaking change(s) detected, but MAJOR version not bumped."
|
|
SUGGESTION="Breaking changes require MAJOR version bump. Consider **v$((MAJOR + 1)).0.0** instead of v$TAG_VERSION"
|
|
elif [ $FEAT -gt 0 ] && [ "$MINOR" = "$PREV_MINOR" ] && [ "$PATCH" != "$PREV_PATCH" ]; then
|
|
WARNING="⚠️ **Version Warning**: $FEAT new feature(s) detected, but only PATCH version bumped."
|
|
SUGGESTION="New features should bump MINOR version. Consider **v$MAJOR.$((MINOR + 1)).0** instead of v$TAG_VERSION"
|
|
fi
|
|
fi
|
|
|
|
# Output warning message
|
|
if [ -n "$WARNING" ]; then
|
|
echo "$WARNING"
|
|
echo "$SUGGESTION"
|
|
echo ""
|
|
echo "Commits analyzed: Breaking=$BREAKING, Features=$FEAT, Fixes=$FIX"
|
|
|
|
# Set output for later steps (using heredoc for multi-line)
|
|
{
|
|
echo "warning<<EOF"
|
|
echo "$WARNING"
|
|
echo ""
|
|
echo "$SUGGESTION"
|
|
echo ""
|
|
echo "**Commits analyzed:** Breaking=$BREAKING, Features=$FEAT, Fixes=$FIX"
|
|
echo ""
|
|
echo "**To fix:**"
|
|
echo "1. Delete the tag: \`git tag -d v$TAG_VERSION && git push origin :refs/tags/v$TAG_VERSION\`"
|
|
echo "2. Run locally: \`./scripts/release/suggest-version\`"
|
|
echo "3. Create correct tag: \`./scripts/release/prepare X.Y.Z\`"
|
|
echo "EOF"
|
|
} >> $GITHUB_OUTPUT
|
|
else
|
|
echo "✓ Version bump looks appropriate for the changes"
|
|
echo "warning=" >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
- name: Install git-cliff
|
|
run: |
|
|
wget https://github.com/orhun/git-cliff/releases/download/v2.4.0/git-cliff-2.4.0-x86_64-unknown-linux-gnu.tar.gz
|
|
tar -xzf git-cliff-2.4.0-x86_64-unknown-linux-gnu.tar.gz
|
|
sudo mv git-cliff-2.4.0/git-cliff /usr/local/bin/
|
|
git-cliff --version
|
|
|
|
- name: Generate release notes
|
|
id: release_notes
|
|
run: |
|
|
FROM_TAG="${{ steps.previoustag.outputs.previous_tag }}"
|
|
TO_TAG="${GITHUB_REF#refs/tags/}"
|
|
|
|
echo "Generating release notes from ${FROM_TAG} to ${TO_TAG}"
|
|
|
|
# Use our script with git-cliff backend (AI disabled in CI)
|
|
# git-cliff will handle filtering via cliff.toml
|
|
USE_AI=false ./scripts/release/generate-notes "${FROM_TAG}" "${TO_TAG}" > release-notes.md
|
|
|
|
# Extract title from release notes (first line starting with "# ")
|
|
TITLE=$(head -n 1 release-notes.md | sed 's/^# //')
|
|
if [ -z "$TITLE" ]; then
|
|
TITLE="Release Updates"
|
|
fi
|
|
echo "title=$TITLE" >> $GITHUB_OUTPUT
|
|
|
|
# Append version warning if present
|
|
WARNING="${{ steps.version_check.outputs.warning }}"
|
|
if [ -n "$WARNING" ]; then
|
|
echo "" >> release-notes.md
|
|
echo "---" >> release-notes.md
|
|
echo "" >> release-notes.md
|
|
echo "$WARNING" >> release-notes.md
|
|
fi
|
|
|
|
# Output for GitHub Actions
|
|
{
|
|
echo 'notes<<EOF'
|
|
cat release-notes.md
|
|
echo EOF
|
|
} >> $GITHUB_OUTPUT
|
|
|
|
- name: Version Check Summary
|
|
if: steps.version_check.outputs.warning != ''
|
|
run: |
|
|
echo "### ⚠️ Version Mismatch Detected" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "${{ steps.version_check.outputs.warning }}" >> $GITHUB_STEP_SUMMARY
|
|
|
|
- name: Create GitHub Release
|
|
uses: softprops/action-gh-release@v2
|
|
with:
|
|
name: ${{ steps.release_notes.outputs.title }}
|
|
body: ${{ steps.release_notes.outputs.notes }}
|
|
draft: false
|
|
prerelease: false
|
|
generate_release_notes: false # We provide our own
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Summary
|
|
run: |
|
|
echo "✅ Release notes generated and published!" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "**Tag:** ${GITHUB_REF#refs/tags/}" >> $GITHUB_STEP_SUMMARY
|
|
echo "**Previous tag:** ${{ steps.previoustag.outputs.previous_tag }}" >> $GITHUB_STEP_SUMMARY
|
|
if [[ "${{ needs.sync-manifest.outputs.updated }}" == "true" ]]; then
|
|
echo "**Manifest sync:** Updated manifest.json to version ${{ needs.sync-manifest.outputs.version }}" >> $GITHUB_STEP_SUMMARY
|
|
else
|
|
echo "**Manifest sync:** No update needed (version already matches)" >> $GITHUB_STEP_SUMMARY
|
|
fi
|
|
if [ -n "${{ steps.version_check.outputs.warning }}" ]; then
|
|
echo "**Version check:** ⚠️ Warning detected (see release notes)" >> $GITHUB_STEP_SUMMARY
|
|
else
|
|
echo "**Version check:** ✓ Version appropriate for changes" >> $GITHUB_STEP_SUMMARY
|
|
fi
|