mirror of
https://github.com/jpawlowski/hass.tibber_prices.git
synced 2026-03-30 05:13:40 +00:00
feat(ci): add manifest sync and version validation to release workflow
Implemented automatic manifest.json synchronization and semantic versioning validation in the release workflow. Auto-Sync Manifest (sync-manifest job): - Extracts version from Git tag (v*.*.*) - Compares with manifest.json version - Auto-updates manifest.json if mismatch detected - Commits changes back to main branch - Sets outputs (updated, version) for downstream jobs - Prevents HACS version mismatches and conflicts with auto-tag.yml Version Check Warning System (version_check step): - Analyzes commits between tags for breaking changes, features, fixes - Applies semantic versioning rules (pre-1.0 and post-1.0) - Detects inappropriate version bumps: - Features with only PATCH bump → suggests MINOR - Breaking changes with only MINOR bump → suggests MAJOR (post-1.0) - Breaking changes with only PATCH bump → suggests MINOR (pre-1.0) - Shows warnings in GitHub Step Summary (prominent) - Appends warnings to release notes body - Provides fix instructions but doesn't fail workflow - Updates final summary with version check status Workflow changes: - release-notes job now depends on sync-manifest - Checks out main branch to get updated manifest if synced - Summary shows manifest sync status and version check result Impact: Prevents manual version tag issues, maintains manifest consistency, and warns about semantic versioning violations without blocking releases. Fully transparent workflow with clear guidance.
This commit is contained in:
parent
ddc718aabd
commit
d7a145d678
1 changed files with 171 additions and 2 deletions
173
.github/workflows/release.yml
vendored
173
.github/workflows/release.yml
vendored
|
|
@ -6,17 +6,86 @@ on:
|
||||||
- 'v*.*.*' # Triggers on version tags like v1.0.0, v2.1.3, etc.
|
- 'v*.*.*' # Triggers on version tags like v1.0.0, v2.1.3, etc.
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write # Needed to create/update releases
|
contents: write # Needed to create/update releases and push commits
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
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@v5
|
||||||
|
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:
|
release-notes:
|
||||||
name: Generate and publish release notes
|
name: Generate and publish release notes
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
needs: sync-manifest # Wait for manifest sync to complete
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0 # Fetch all history for git-cliff
|
fetch-depth: 0 # Fetch all history for git-cliff
|
||||||
|
ref: main # Use updated main branch if manifest was synced
|
||||||
|
|
||||||
- name: Get previous tag
|
- name: Get previous tag
|
||||||
id: previoustag
|
id: previoustag
|
||||||
|
|
@ -25,6 +94,78 @@ jobs:
|
||||||
echo "previous_tag=${PREVIOUS_TAG}" >> $GITHUB_OUTPUT
|
echo "previous_tag=${PREVIOUS_TAG}" >> $GITHUB_OUTPUT
|
||||||
echo "Previous tag: ${PREVIOUS_TAG}"
|
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/suggest-version\`"
|
||||||
|
echo "3. Create correct tag: \`./scripts/prepare-release 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
|
- name: Install git-cliff
|
||||||
run: |
|
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
|
wget https://github.com/orhun/git-cliff/releases/download/v2.4.0/git-cliff-2.4.0-x86_64-unknown-linux-gnu.tar.gz
|
||||||
|
|
@ -44,12 +185,30 @@ jobs:
|
||||||
# git-cliff will handle filtering via cliff.toml
|
# git-cliff will handle filtering via cliff.toml
|
||||||
USE_AI=false ./scripts/generate-release-notes "${FROM_TAG}" "${TO_TAG}" > release-notes.md
|
USE_AI=false ./scripts/generate-release-notes "${FROM_TAG}" "${TO_TAG}" > release-notes.md
|
||||||
|
|
||||||
|
# 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
|
# Output for GitHub Actions
|
||||||
{
|
{
|
||||||
echo 'notes<<EOF'
|
echo 'notes<<EOF'
|
||||||
cat release-notes.md
|
cat release-notes.md
|
||||||
echo EOF
|
echo EOF
|
||||||
} >> $GITHUB_OUTPUT - name: Create GitHub Release
|
} >> $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
|
uses: softprops/action-gh-release@v2
|
||||||
with:
|
with:
|
||||||
body: ${{ steps.release_notes.outputs.notes }}
|
body: ${{ steps.release_notes.outputs.notes }}
|
||||||
|
|
@ -65,3 +224,13 @@ jobs:
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "**Tag:** ${GITHUB_REF#refs/tags/}" >> $GITHUB_STEP_SUMMARY
|
echo "**Tag:** ${GITHUB_REF#refs/tags/}" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "**Previous tag:** ${{ steps.previoustag.outputs.previous_tag }}" >> $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
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue