The project is in a healthy, maintained state
Parse Keep a Changelog formatted markdown files with version querying, category management, release creation, and markdown write-back support.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies
 Project Readme

philiprehberger-changelog_parser

Tests Gem Version Last updated

Parser for Keep a Changelog format with querying and write-back

Requirements

  • Ruby >= 3.1

Installation

Add to your Gemfile:

gem "philiprehberger-changelog_parser"

Or install directly:

gem install philiprehberger-changelog_parser

Usage

require "philiprehberger/changelog_parser"

changelog = Philiprehberger::ChangelogParser.parse('CHANGELOG.md')
changelog.versions   # => ['Unreleased', '0.2.0', '0.1.0']
changelog.latest     # => VersionEntry for 0.2.0

Querying Versions

entry = changelog.version('0.2.0')
entry.date                  # => '2026-03-20'
entry.categories['Added']   # => ['New feature A', 'New feature B']

Adding Entries

changelog.add('Unreleased', 'Added', 'New search feature')
changelog.add('Unreleased', 'Fixed', 'Resolved login bug')

Releasing a Version

changelog.release('0.3.0', date: '2026-03-22')
# Moves Unreleased entries to the new version

Writing Back

changelog.write('CHANGELOG.md')
# Or get the markdown string
markdown = changelog.to_markdown

JSON Serialization

json = changelog.to_json
# => '{"title":"Changelog","versions":[{"version":"Unreleased","date":null,"categories":{}},...]}'

Comparing Versions

require "philiprehberger/changelog_parser"

changelog = Philiprehberger::ChangelogParser.parse("CHANGELOG.md")

# Get all changes between two versions
changes = changelog.diff("0.1.0", "0.3.0")
changes["Added"]  # => ["Feature B", "Feature C"]

# Get all changes since a version
recent = changelog.since("0.1.0")
recent["Fixed"]   # => ["Bug fix B"]

Searching Entries

results = changelog.search("authentication")
results.each do |match|
  puts "#{match[:version]} [#{match[:category]}] #{match[:entry]}"
end

# Also accepts regex
changelog.search(/\bbug\b/i)

Validation

warnings = changelog.validate
# => ["empty version: 0.2.0", "date out of order: 2026-03-01 before 2026-03-15"]

Filtering by Category

added = changelog.filter(category: 'Added')
added.each do |match|
  puts "#{match[:version]} (#{match[:date]}): #{match[:entry]}"
end

Removing Entries

changelog.remove('Unreleased', 'Added', 'Obsolete feature')

JSON Round-Trip

json = changelog.to_json
restored = Philiprehberger::ChangelogParser.from_json(json)
restored.versions  # => same as original

Parsing Strings

changelog = Philiprehberger::ChangelogParser.parse(<<~MD)
  # Changelog

  ## [Unreleased]

  ## [0.1.0] - 2026-03-15

  ### Added
  - Initial release
MD

API

ChangelogParser

Method Description
.parse(path_or_string) Parse a changelog from a file path or string
.from_json(json_string) Deserialize a changelog from a JSON string

Changelog

Method Description
#versions Return all version strings
#version(v) Find a specific version entry
#unreleased Return the Unreleased entry
#latest Return the latest released version
#add(version, category, entry) Add an entry to a version
#remove(version, category, entry) Remove an entry from a version
#release(version, date:) Create a release from Unreleased
#write(path) Write changelog to a file
#diff(from, to) Returns merged entries between two versions
#since(version) Returns merged entries newer than a version
#filter(category:) Return all entries from a specific category across versions
#search(query) Search entries by keyword or regex
#validate Check for common issues (duplicates, date order, empty versions)
#to_json Serialize as JSON string
#to_markdown Render as markdown string

VersionEntry

Method Description
#version The version string
#date The release date
#categories Hash of category to entries
#empty? True if version has no entries

Development

bundle install
bundle exec rspec
bundle exec rubocop

Support

If you find this project useful:

Star the repo

🐛 Report issues

💡 Suggest features

❤️ Sponsor development

🌐 All Open Source Projects

💻 GitHub Profile

🔗 LinkedIn Profile

License

MIT