Semmy

Gem Version Dependency Status Build Status Coverage Status Code Climate

An opinionated set of rake tasks to maintain gems following semantic versioning principles.

Assumptions

Git Branches and Tags

Development happens directly on master or by merging pull requests. When a release is made, a stable branch called x-y-stable is created. Semmy relies on Bundler's release task to create version tags.

Patch level versions are released via backports to the stable branches.

Version Suffix

The version in the gem's version file is increased in a separate commit right after release. The version always has an dev suffix (i.e. 1.1.0.dev), which is only removed in the last commit preparing the release. That way it is easy to see in a project's Gemfile.lock whether an unreleased version is used.

Patch level versions are expected to be released immediately after backporting bug fixes. So there are never commits with a version suffix on stable branches.

Doc Tags

Pull requests introducing new features, are expected to markup new code elements with a @since edge doc tag. When a release is prepared, edge is replaced with the current version string. That way pull request authors do not have to guess, which version will merge their commits.

Changelog

Unreleased changes are listed in a section at the top. When preparing a release this section is closed by placing a version heading above it and inserting a compare link. Changelog entries for patch level versions are only committed on the stable branches since they only backport bug fixes from master.

Installation

Add development dependency to your gemspec:

# your.gemspec
s.add_development_dependency 'semmy', '~> 1.0'

Install gems:

$ bundle

Add the tasks to your Rakefile:

# Rakefile
require 'semmy'

Semmy::Tasks.install

You can pass config options:

# Rakefile
require 'semmy'

Semmy::Tasks.install do |config|
  # see Semmy::Configuration for options
end

Usage

Semmy defines a new task to prepare a release:

$ rake release:prepare

This task:

  • Ensures the gem can be installed.
  • Removes the dev version suffix from the version file.
  • Rewrites doc tags.
  • Closes the section of the new version in the changelog.
  • Commits the changes.

It is expected that a release task exists. Normally this tasks is provided by Bundler.

$ rake release

Semmy registers additional actions which shall be executed right after the release:

  • Creates a stable branch.
  • Bumps the version to the next minor version with alpha version suffix.
  • Inserts an "Unreleased Changes" section in the changelog.

The resulting commit graph looks like:

* (master) Bump version to 1.3.0.dev
* (v1.2.0, 1-2-stable) Prepare 1.2.0 release
* Some new feature

By default, the new stable branch and the bump commit are not pushed automatically. This can be activated by setting the push_branches_after_release config option to true.

This will be the new default once Semmy 2.0 is released. You can opt into the future default behavior globally without changing config options on the project level by setting the SEMMY_PUSH_BRANCHES_AFTER_RELEASE environment variable to on.

Branches will be pushed to the remote passed as an argument to the release task:

$ rake release[upstream]

By default, branches are pushed to origin.

Releasing a Patch Level Version

Assume an important bug fix has been added to master:

* (master) Important bug fix
* First new feature
* Bump version to 1.3.0.dev
* (v1.0.0, 1-2-stable) Prepare 1.2.0 release

check out the stable branch and cherry pick commits:

$ git checkout 1-2-stable
$ git cherry-pick master

Then run:

$ rake bump:patch

This task:

  • Bumps the version to 1.2.1 in the version file.
  • Inserts an "Unreleased Changes" section in the changelog.

Add items to the new changelog section, then run:

$ rake release:prepare

This task detects that we are currently on a stable branch and performs the following subset of the normal prepare tasks:

  • Closes the section of the new version in the changelog.
  • Commits the changes

You can now run rake release, leaving you with the following commit graph:

* (master) Important bug fix
* First new feature
* Bump version to 1.3.0.dev
| * (v1.2.1, 1-2-stable) Prepare 1.2.1 release
| * Important bug fix
|/
* (v1.2.0) Prepare 1.2.0 release

Releasing a Major Version

If breaking changes have been merged to master, run:

$ rake bump:major

Assuming the version was 1.2.0.dev before, This bumps the major version in the version file to 2.0.0.dev and updates the changelog to reference 1-x-stable for comparison.

The branch 1-x-stable has to be created and managed manually. It should always point to the same commit as the lastest minor version stable branch of the major version.

The rest of the release can be performed like a normal minor version release.

Development

After checking out the repo, run bin/setup to install dependencies. You can also run bin/console for an interactive prompt that will allow you to experiment. Run bin/rspec to execute the test suite.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/tf/semmy.

License

The gem is available as open source under the terms of the MIT License.