Low commit activity in last 3 years
A lightweight Ruby library for parsing, comparing, sorting, and matching semantic versions per the SemVer 2.0.0 specification.
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-semver

Tests Gem Version Last updated

SemVer 2.0.0 parsing, comparison, range matching, and bump operations

Requirements

  • Ruby >= 3.1

Installation

Add to your Gemfile:

gem "philiprehberger-semver"

Or install directly:

gem install philiprehberger-semver

Usage

require "philiprehberger/semver"

# Parse a version string
version = Philiprehberger::Semver.parse('1.2.3-beta.1+build.123')
version.major          # => 1
version.minor          # => 2
version.patch          # => 3
version.pre_release    # => 'beta.1'
version.build_metadata # => 'build.123'
version.to_s           # => '1.2.3-beta.1+build.123'

Comparison

Versions implement Comparable, so all standard Ruby comparison operators work. Pre-release versions sort lower than their release counterpart, and pre-release identifiers are compared per SemVer 2.0.0 precedence rules.

Philiprehberger::Semver.parse('2.0.0') > Philiprehberger::Semver.parse('1.9.9')   # => true
Philiprehberger::Semver.parse('1.0.0-alpha') < Philiprehberger::Semver.parse('1.0.0')  # => true
Philiprehberger::Semver.parse('1.0.0-alpha') < Philiprehberger::Semver.parse('1.0.0-beta')  # => true
Philiprehberger::Semver.parse('1.0.0-alpha.1') < Philiprehberger::Semver.parse('1.0.0-alpha.2')  # => true

Sorting

Pass an array of version strings and get back a sorted array in ascending order.

Philiprehberger::Semver.sort(['2.0.0', '1.0.0', '1.1.0'])
# => ['1.0.0', '1.1.0', '2.0.0']

Philiprehberger::Semver.sort(['1.0.0', '1.0.0-alpha', '1.0.0-beta'])
# => ['1.0.0-alpha', '1.0.0-beta', '1.0.0']

Bumping

bump returns a new immutable Version with the specified level incremented. Minor and patch are reset to zero when a higher level is bumped.

version = Philiprehberger::Semver.parse('1.2.3')
version.bump(:major).to_s  # => '2.0.0'
version.bump(:minor).to_s  # => '1.3.0'
version.bump(:patch).to_s  # => '1.2.4'

Iterating pre-release identifiers

next_pre_release returns a new immutable Version with its pre-release identifier iterated. A stable version is promoted to a pre-release using the given label: (default 'alpha'). A version that already has a pre-release has its trailing numeric token incremented; if the last token is not numeric, .1 is appended. The label: keyword is ignored when the version is already a pre-release. build_metadata is preserved.

Philiprehberger::Semver.parse('1.2.3').next_pre_release.to_s               # => '1.2.3-alpha.1'
Philiprehberger::Semver.parse('1.2.3').next_pre_release(label: 'beta').to_s # => '1.2.3-beta.1'
Philiprehberger::Semver.parse('1.0.0-alpha.1').next_pre_release.to_s       # => '1.0.0-alpha.2'
Philiprehberger::Semver.parse('1.0.0-rc.4').next_pre_release.to_s          # => '1.0.0-rc.5'
Philiprehberger::Semver.parse('1.0.0-rc').next_pre_release.to_s            # => '1.0.0-rc.1'
Philiprehberger::Semver.parse('1.0.0-alpha.beta').next_pre_release.to_s    # => '1.0.0-alpha.beta.1'

Stripping pre-release

strip_prerelease returns a new immutable Version with the pre-release identifier removed. Build metadata is preserved.

v = Philiprehberger::Semver.parse('1.2.3-rc.1')
v.strip_prerelease.to_s # => "1.2.3"

Philiprehberger::Semver.parse('1.2.3-rc.1+build.5').strip_prerelease.to_s # => "1.2.3+build.5"

Pre-release identifiers

prerelease_identifiers returns the dot-separated pre-release identifiers as an array of strings. Numeric identifiers stay as strings (per SemVer 2.0.0). Versions without a pre-release segment return an empty array.

Philiprehberger::Semver.parse('1.2.3-beta.1').prerelease_identifiers    # => ["beta", "1"]
Philiprehberger::Semver.parse('1.2.3').prerelease_identifiers           # => []
Philiprehberger::Semver.parse('1.0.0-rc.1+build.42').prerelease_identifiers # => ["rc", "1"]

Version Predicates

require "philiprehberger/semver"

version = Philiprehberger::Semver.parse("1.0.0-alpha")
version.pre_release?  # => true
version.stable?       # => false

stable = Philiprehberger::Semver.parse("2.1.0")
stable.stable?        # => true
stable.to_a           # => [2, 1, 0]

Range Matching

Check whether a version satisfies one or more comma-separated constraints. Supports standard comparison operators, pessimistic (~>), and caret (^) constraints.

Philiprehberger::Semver.satisfies?('1.5.0', '>= 1.0.0, < 2.0.0')  # => true
Philiprehberger::Semver.satisfies?('1.5.0', '~> 1.4')              # => true
Philiprehberger::Semver.satisfies?('1.9.0', '^ 1.0.0')             # => true
Philiprehberger::Semver.satisfies?('2.0.0', '>= 1.0.0, < 2.0.0')  # => false

API

Philiprehberger::Semver

Method Description
.parse(string) Parse a SemVer string into a Version object
.satisfies?(version_str, constraint) Check if a version satisfies a constraint string
.sort(versions) Sort an array of version strings

Philiprehberger::Semver::Version

Method Description
#major Major version number
#minor Minor version number
#patch Patch version number
#pre_release Pre-release identifier or nil
#prerelease_identifiers Dot-separated pre-release identifiers as Array<String>, or [] if none
#build_metadata Build metadata or nil
#bump(level) Return a new Version bumped at :major, :minor, or :patch
#next_pre_release(label:) Return a new Version with its pre-release iterated (promotes stable, or bumps trailing numeric token)
#strip_prerelease Returns a new Version with the pre-release stripped (preserves build metadata)
#pre_release? true if the version has a pre-release segment
#stable? true if major >= 1 and no pre-release
#to_a Return [major, minor, patch] as an array
#to_s Format as a SemVer string
#<=> Compare two versions per SemVer 2.0.0 precedence rules

Supported Constraint Operators

Operator Example Description
>= >= 1.0.0 Greater than or equal
<= <= 2.0.0 Less than or equal
> > 1.0.0 Greater than
< < 2.0.0 Less than
= = 1.0.0 Exact match
~> ~> 1.4 Pessimistic (same major, minor >= target)
^ ^ 1.0.0 Compatible (same major)

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