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<> $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/generate-release-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<> $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