Agent Skills: Update Changelog

Update CHANGELOG.md comprehensively based on git tags, merged PRs, and actual code diffs. Use when the user asks to "update the changelog", backfill missing versions, prepare a release, or reconcile [Unreleased] entries against shipped tags. Produces Keep-a-Changelog entries that describe user-facing impact, not implementation details.

UncategorizedID: letsrevel/revel-backend/update-changelog

Install this agent skill to your local

pnpm dlx add-skill https://github.com/letsrevel/revel-backend/tree/HEAD/.claude/skills/update-changelog

Skill Files

Browse the full folder contents for update-changelog.

Download Skill

Loading file tree…

.claude/skills/update-changelog/SKILL.md

Skill Metadata

Name
update-changelog
Description
Update CHANGELOG.md comprehensively based on git tags, merged PRs, and actual code diffs. Use when the user asks to "update the changelog", backfill missing versions, prepare a release, or reconcile [Unreleased] entries against shipped tags. Produces Keep-a-Changelog entries that describe user-facing impact, not implementation details.

Update Changelog

Maintains CHANGELOG.md (Keep a Changelog format, semver) by reconciling it against git tags, merged PRs, and actual code diffs.

Format conventions (this repo)

  • Header: ## [X.Y.Z] - YYYY-MM-DD for released versions, ## [Unreleased] at the top.
  • Section order: Added, Changed, Fixed, Deprecated, Removed, Security. Omit empty sections.
  • Bullets describe user/operator/API-consumer impact, not internal refactors. Drop pure CI/test/lint commits unless they change observable behavior.
  • Major features get a bold prefix: - **VAT Support**: Complete VAT handling for ticket sales…. Optional nested sub-bullets for sub-features.
  • Bug fixes name the symptom that was fixed, not the patch ("location_maps_url max length increased from 200 to 2048 to accommodate long Google Maps URLs").
  • Dates are the tag date (committer date of the tag), not today's date.

Release model (this repo)

  • make release runs gh release create v$VERSION --generate-notes using version from pyproject.toml.
  • A "bump X.Y.Z" PR (often bundled with small fixes — e.g. chore: bundled fixes (...) + bump 1.55.0) lands on main, then make release is invoked.
  • CHANGELOG.md must be updated in the same commit that bumps pyproject.toml — write the new ## [X.Y.Z] - YYYY-MM-DD section before the bump PR is merged.

Workflow

1. Establish state

git tag --sort=-v:refname | head -20             # latest tags
grep -E '^## \[' CHANGELOG.md | head -10         # versions present in changelog
grep '^version = ' pyproject.toml                 # pending version

Compare the three. Common situations:

  • Behind on tags — CHANGELOG missing released versions → backfill each gap (step 2 per gap).
  • [Unreleased] populated, pyproject bumped — promote [Unreleased] to ## [X.Y.Z] - <tag-date> and start a fresh empty [Unreleased].
  • New work since last tag — add entries to [Unreleased] only.

2. Gather changes between two refs

For each version gap vA..vB (or vLast..HEAD for unreleased):

# 1. Tag date for the section header
git log -1 --format=%cs vB                          # YYYY-MM-DD

# 2. Merged PRs in the range (richest signal — PR titles are usually user-facing)
git log vA..vB --merges --format='%h %s' --first-parent

# 3. Full commit subjects on main (catch non-PR commits)
git log vA..vB --format='%h %s' --first-parent

# 4. For each non-trivial PR, read its body for the user-facing description
gh pr view <number> --json title,body,labels

Group commits by prefix (feat:, fix:, refactor:, chore:, test:, docs:, ci:) as a first pass — but do not trust the prefix alone (see step 3).

3. Verify impact from the diff

A commit message says what the author intended; the diff says what actually changed. For any entry where impact is unclear or the message is terse:

git show <sha> --stat                               # which files moved
git show <sha> -- <interesting-path>                # the actual change
git diff vA..vB -- src/<app>/                       # cumulative for a subsystem

Verify the user-facing surface:

  • New endpoints / changed schemas → check events/controllers/, accounts/controllers/, */schema/, openapi.json if regenerated.
  • New models or migrations → check */models/, */migrations/00XX_*.py (squashed migrations matter for ops).
  • Settings or env vars → check src/revel/settings/, .env*, CLAUDE.md.
  • Background jobs / Celery → check */tasks.py, celery.py beat schedule.
  • Permissions / auth → check events/controllers/permissions.py, common/auth/.

If the diff is purely internal (renames, helper extraction, type hints, test reorg) and there is no observable change, drop it — even if the commit was feat:-prefixed.

4. Categorize

| Section | Use for | |---------|---------| | Added | New features, new endpoints, new models, new settings/flags, new notification channels, new file format support | | Changed | Behavior changes to existing features, API contract changes (non-breaking), default-value changes, performance changes visible to users | | Fixed | Bug fixes — describe the symptom | | Deprecated | Features still working but slated for removal | | Removed | Removed features, endpoints, settings | | Security | Auth fixes, permission tightenings, vulnerability patches (do not name the CVE if not public) |

Bundle related commits into one bullet. A feature that spans 5 PRs becomes one bold-prefixed bullet, optionally with sub-bullets per sub-feature.

5. Write entries

Style examples lifted from this repo's existing entries — match the voice:

### Added
- **Referral System — Full Launch**: Complete referral program with Stripe auto-payouts
  - `UserBillingProfile` model for referrer billing details (VAT ID, address, self-billing agreement)
  - Monthly payout calculation task aggregating net platform fees per referral
- VAT preview endpoint for checkout (`POST /events/{event_id}/tickets/vat-preview`) with buyer-specific VAT calculation and VIES caching (Redis, 30-minute TTL)

### Fixed
- Unbanning a user now clears the stale `BANNED` `OrganizationMember` row that the ban created.
- Follower notifications (`NEW_EVENT_FROM_FOLLOWED_ORG`) no longer sent for non-public events

Rules:

  • Lead with the what, not the how. ("Discord admin-ping channel" not "Added discord_admin_webhook_url setting and send_discord_admin_ping function").
  • Backticks for code symbols (model names, field names, env vars, endpoints).
  • Bold prefix **Name**: only for headline features that warrant top-billing.
  • One sentence per bullet; sub-bullets for multi-part features.
  • No author/PR-number/issue-number references — those live in commit history and PRs.

6. Insert into the file

  • [Unreleased] always stays at the top, even if empty (with no subsections), so future entries have a home.
  • New released sections go directly under [Unreleased], in descending version order.
  • When promoting [Unreleased] to a version: copy the content under a new ## [X.Y.Z] - <tag-date> heading and leave [Unreleased] empty.
  • Preserve any existing [Unreleased] entries — they may already document work in the new version.

7. Verify

# Visual diff
git diff CHANGELOG.md

# Sanity check: every tag from vA..latest has a section
git tag --sort=-v:refname | head -20
grep -E '^## \[' CHANGELOG.md

Do not run make release or push tags — the skill only edits CHANGELOG.md. The user runs make release themselves.

Anti-patterns

  • ❌ Dumping every commit subject as a bullet. Filter, group, rewrite.
  • ❌ Using the date of editing as the section date — use the tag's commit date.
  • ❌ Trusting feat: / fix: prefixes without checking the diff.
  • ❌ Mentioning internal refactors, test additions, type fixes, or CI changes unless they affect users/operators.
  • ❌ Inventing impact you can't confirm from the diff. If unsure, ask the user or omit.
  • ❌ Overwriting existing [Unreleased] content when promoting it — merge, don't replace.
  • ❌ Editing pyproject.toml or creating tags. Out of scope for this skill.