Skip to content

Commit 6643428

Browse files
bitwize-musicclaude
andcommitted
refactor: remove automated CHANGELOG commits for security
Based on security research, allowing github-actions bot to bypass branch protection creates attack vectors for malicious workflows. Following best practices from Google's release-please and industry standards, CHANGELOG.md is now manually maintained. Changes: - Remove CHANGELOG auto-update and commit steps from workflow - Add verification step to check CHANGELOG was updated - Update documentation to reflect manual process - Simplifies workflow and eliminates branch protection conflicts Security benefits: - No bypass permissions needed (eliminates attack surface) - Manual review ensures quality release notes - Follows GitHub security best practices - Matches workflow used by major OSS projects References: - https://medium.com/cider-sec/bypassing-required-reviews-using-github-actions-6e1b29135cc7 - https://github.com/googleapis/release-please-action Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 5e1539f commit 6643428

3 files changed

Lines changed: 19 additions & 49 deletions

File tree

.github/workflows/auto-release.yml

Lines changed: 12 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -79,53 +79,19 @@ jobs:
7979
--notes-file /tmp/release_notes.md \
8080
$PRERELEASE
8181
82-
- name: Update CHANGELOG
82+
- name: Verify CHANGELOG was updated
8383
if: steps.check_tag.outputs.exists == 'false'
84-
env:
85-
RELEASE_VERSION: ${{ steps.version.outputs.version }}
86-
run: |
87-
export RELEASE_DATE=$(date +%Y-%m-%d)
88-
89-
python3 << 'PYTHON_SCRIPT'
90-
import os
91-
import re
92-
from datetime import date
93-
94-
version = os.environ['RELEASE_VERSION']
95-
release_date = os.environ['RELEASE_DATE']
96-
97-
with open('CHANGELOG.md', 'r') as f:
98-
content = f.read()
99-
100-
# Replace [Unreleased] with [X.Y.Z] - DATE
101-
content = content.replace('## [Unreleased]', f'## [{version}] - {release_date}')
102-
103-
# Add new [Unreleased] section
104-
new_section = "## [Unreleased]\n\n### Added\n\n### Changed\n\n### Fixed\n\n"
105-
# Insert new section before the versioned release
106-
content = content.replace(f'## [{version}] - {release_date}', new_section + f'## [{version}] - {release_date}')
107-
108-
with open('CHANGELOG.md', 'w') as f:
109-
f.write(content)
110-
111-
print("CHANGELOG.md updated")
112-
PYTHON_SCRIPT
113-
114-
- name: Commit CHANGELOG update
115-
if: steps.check_tag.outputs.exists == 'false'
116-
continue-on-error: true
11784
run: |
118-
git config user.name "github-actions[bot]"
119-
git config user.email "github-actions[bot]@users.noreply.github.com"
120-
git add CHANGELOG.md
85+
VERSION="${{ steps.version.outputs.version }}"
12186
122-
# Only commit if there are changes
123-
if git diff --cached --quiet; then
124-
echo "No CHANGELOG changes to commit"
125-
exit 0
87+
# Check if this version exists in CHANGELOG
88+
if grep -q "## \[$VERSION\]" CHANGELOG.md; then
89+
echo "✅ CHANGELOG.md contains release notes for version $VERSION"
90+
else
91+
echo "⚠️ WARNING: CHANGELOG.md does not contain section for version $VERSION"
92+
echo ""
93+
echo "The release was created, but please update CHANGELOG.md manually:"
94+
echo "1. Rename [Unreleased] to [$VERSION] - $(date +%Y-%m-%d)"
95+
echo "2. Add new [Unreleased] section above it"
96+
echo "3. Commit and push to main"
12697
fi
127-
128-
git commit -m "chore: update CHANGELOG for ${{ steps.version.outputs.version }} release [skip ci]"
129-
130-
# Try to push, but don't fail if branch protection prevents it
131-
git push || echo "⚠️ Could not push CHANGELOG update due to branch protection. Please update manually."

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ This project uses [Conventional Commits](https://conventionalcommits.org/) and [
99
### Added
1010

1111
### Changed
12+
- CHANGELOG.md is now manually maintained (no automated commits) for security and quality
13+
- Auto-release workflow verifies CHANGELOG was updated instead of attempting to modify it
1214

1315
### Fixed
14-
- Auto-release workflow now continues successfully even when branch protection prevents CHANGELOG commit
1516

1617
## [0.5.1] - 2026-01-25
1718

CLAUDE.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,17 @@ This plugin uses [Semantic Versioning](https://semver.org/) with [Conventional C
4040
**Release process:**
4141
1. Update entries in `CHANGELOG.md` under `[Unreleased]` as you work
4242
2. When ready to release:
43+
- Finalize `CHANGELOG.md`: Rename `[Unreleased]``[0.x.0] - YYYY-MM-DD`
44+
- Add new `[Unreleased]` section above it
4345
- Update version in `.claude-plugin/plugin.json`
4446
- Update version in `.claude-plugin/marketplace.json` (must match plugin.json)
4547
3. Commit: `chore: release 0.x.0`
4648
4. Push to main → **Automated workflow**:
4749
- Creates git tag `v0.x.0`
4850
- Creates GitHub release with CHANGELOG notes
49-
- Updates CHANGELOG.md (renames [Unreleased][0.x.0] with date)
50-
- Commits CHANGELOG update back to main
51+
- Verifies CHANGELOG was updated for this version
52+
53+
**Note:** CHANGELOG.md is manually maintained to ensure quality release notes and maintain security (no branch protection bypass needed).
5154

5255
**Version files (must stay in sync):**
5356
- `.claude-plugin/plugin.json` - Plugin manifest

0 commit comments

Comments
 (0)