Skip to content

Merge pull request #11 from zopiolabs/changelog-update-0.2.0 #7

Merge pull request #11 from zopiolabs/changelog-update-0.2.0

Merge pull request #11 from zopiolabs/changelog-update-0.2.0 #7

Workflow file for this run

# Automated Changelog Generation and Release Creation
#
# Purpose: Automatically generates a CHANGELOG.md file based on conventional commits
# and creates GitHub releases with proper versioning.
#
# Triggers:
# - Push to main branch (automatic)
# - Manual workflow dispatch (on-demand)
#
# Features:
# - Uses conventional commits to determine version bumps
# - Generates changelog in Angular preset format
# - Creates semantic version tags (v1.2.3)
# - Publishes GitHub releases with changelog content
# - Commits changelog updates back to repository
#
# Required permissions:
# - contents: write (to push changelog commits)
# - pull-requests: write (for PR interactions)
name: Generate Changelog
on:
push:
branches:
- main
workflow_dispatch: # Allow manual trigger from GitHub UI
# Prevent multiple changelog generations at the same time
concurrency:
group: changelog-${{ github.ref }}
cancel-in-progress: false # Don't cancel changelog generation
permissions:
contents: write # Required to push commits and create tags
pull-requests: write # Required for PR-related operations
jobs:
changelog:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0 # Fetch complete history for accurate changelog generation
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
- name: Generate changelog
uses: TriPSs/conventional-changelog-action@v5
id: changelog
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
# Commit message format for changelog updates
git-message: 'chore(release): update CHANGELOG.md for {version}'
# Bot identity for commits
git-user-name: 'zopio-bot'
git-user-email: 'bot@zopio.dev'
# Use Angular commit convention for parsing
preset: 'angular'
# Version tags will be formatted as v1.2.3
tag-prefix: 'v'
# Output changelog to root directory
output-file: 'CHANGELOG.md'
# Include all releases in changelog (0 = all)
release-count: 0
# Update package.json version
skip-version-file: false
version-file: './package.json'
version-path: 'version'
# Skip commit and tag creation - we'll handle this via PR
skip-commit: true
skip-tag: true
# Skip git pull to avoid conflicts
skip-git-pull: true
# Generate GitHub Action summary
create-summary: true
# Debug: Show what files were modified
- name: Debug - Check modified files
if: ${{ steps.changelog.outputs.skipped == 'false' }}
run: |
echo "=== Git Status ==="
git status
echo ""
echo "=== Git Diff ==="
git diff --name-only
echo ""
echo "=== Package.json version ==="
cat package.json | grep '"version"'
echo ""
echo "=== CHANGELOG.md first 10 lines ==="
head -10 CHANGELOG.md
# Verify that package.json was updated
- name: Verify version update
if: ${{ steps.changelog.outputs.skipped == 'false' }}
run: |
EXPECTED_VERSION="${{ steps.changelog.outputs.version }}"
ACTUAL_VERSION=$(node -p "require('./package.json').version")
if [ "$ACTUAL_VERSION" != "$EXPECTED_VERSION" ]; then
echo "❌ Error: package.json version ($ACTUAL_VERSION) does not match expected version ($EXPECTED_VERSION)"
echo "This indicates the conventional-changelog-action failed to update package.json"
# Manually update package.json if needed
echo "Attempting manual version update..."
npm version $EXPECTED_VERSION --no-git-tag-version
# Verify the manual update worked
NEW_VERSION=$(node -p "require('./package.json').version")
if [ "$NEW_VERSION" != "$EXPECTED_VERSION" ]; then
echo "❌ Manual version update failed"
exit 1
fi
echo "✅ Manually updated package.json to version $EXPECTED_VERSION"
else
echo "✅ package.json version correctly updated to $EXPECTED_VERSION"
fi
# Create a new branch for the changelog update
- name: Create changelog branch
if: ${{ steps.changelog.outputs.skipped == 'false' }}
run: |
git config --local user.email "bot@zopio.dev"
git config --local user.name "zopio-bot"
BRANCH_NAME="changelog-update-${{ steps.changelog.outputs.version }}"
git checkout -b $BRANCH_NAME
# Check if files were actually modified
if git diff --quiet CHANGELOG.md; then
echo "❌ Error: CHANGELOG.md was not modified"
exit 1
fi
# Add files and show what's being committed
git add CHANGELOG.md package.json
echo "Files to be committed:"
git status --porcelain
# Commit with detailed message
git commit -m "chore(release): update changelog for v${{ steps.changelog.outputs.version }}" \
-m "- Updated CHANGELOG.md with version ${{ steps.changelog.outputs.version }}" \
-m "- Updated package.json version to ${{ steps.changelog.outputs.version }}"
git push origin $BRANCH_NAME
echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV
# Create PR for changelog update
- name: Create Pull Request
id: create-pr
if: ${{ steps.changelog.outputs.skipped == 'false' }}
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
// Get the modified files
const { stdout: modifiedFiles } = await exec.getExecOutput('git', ['diff', '--name-only', 'origin/main']);
const filesList = modifiedFiles.trim().split('\n').filter(f => f);
const { data: pr } = await github.rest.pulls.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: `chore(release): update changelog for v${{ steps.changelog.outputs.version }}`,
head: process.env.BRANCH_NAME,
base: 'main',
body: `## Changelog Update
This PR updates the CHANGELOG.md for version v${{ steps.changelog.outputs.version }}.
### Changes included:
- ✅ Updated CHANGELOG.md with latest changes
- ✅ Bumped version in package.json to ${{ steps.changelog.outputs.version }}
### Modified files:
${filesList.map(f => `- \`${f}\``).join('\n')}
### Release notes:
${{ steps.changelog.outputs.clean_changelog }}
### Validation:
- Repository: \`${{ github.repository }}\`
- Version: \`${{ steps.changelog.outputs.version }}\`
- Tag: \`${{ steps.changelog.outputs.tag }}\`
---
*This PR was automatically generated by the changelog workflow.*`
});
core.setOutput('pull-request-number', pr.number);
core.setOutput('pull-request-url', pr.html_url);
// Log PR creation details
console.log(`✅ Created PR #${pr.number}: ${pr.html_url}`);
# Add PR validation comment
- name: Add validation comment to PR
if: ${{ steps.changelog.outputs.skipped == 'false' && steps.create-pr.outputs.pull-request-number }}
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const prNumber = ${{ steps.create-pr.outputs.pull-request-number }};
// Verify files in the PR
const { data: files } = await github.rest.pulls.listFiles({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber
});
const hasChangelog = files.some(f => f.filename === 'CHANGELOG.md');
const hasPackageJson = files.some(f => f.filename === 'package.json');
let validationMessage = '## 🔍 Automated Validation Results\n\n';
if (hasChangelog && hasPackageJson) {
validationMessage += '✅ **All required files updated successfully:**\n';
validationMessage += '- CHANGELOG.md ✓\n';
validationMessage += '- package.json ✓\n\n';
validationMessage += '### Version Information\n';
validationMessage += `- New version: \`${{ steps.changelog.outputs.version }}\`\n`;
validationMessage += `- Tag to be created: \`${{ steps.changelog.outputs.tag }}\`\n`;
} else {
validationMessage += '❌ **Missing required files:**\n';
validationMessage += `- CHANGELOG.md: ${hasChangelog ? '✓' : '✗ MISSING'}\n`;
validationMessage += `- package.json: ${hasPackageJson ? '✓' : '✗ MISSING'}\n\n`;
validationMessage += '⚠️ **Action Required:** Please review and fix the missing files.\n';
}
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: validationMessage
});
# Create GitHub release after PR is created
- name: Create Release
if: ${{ steps.changelog.outputs.skipped == 'false' }}
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.changelog.outputs.tag }} # e.g., v1.2.3
release_name: Release ${{ steps.changelog.outputs.tag }} # Release title
body: |
## What's Changed
${{ steps.changelog.outputs.clean_changelog }}
---
**Full Changelog**: https://github.com/${{ github.repository }}/blob/main/CHANGELOG.md
📝 Note: This release is in draft mode. It will be published when PR #${{ steps.create-pr.outputs.pull-request-number }} is merged.
draft: true # Create as draft until PR is merged
prerelease: false # Mark as stable release