2018-07-16
Releasing a new version of a Haskell package to Hackage requires quite a few steps. I wanted to make a list of the steps here on my blog so that it is easy for people to refer to them when trying make a new release of a package. It is better to have a simple checklist to follow than to have to remember all the steps each time.1
The steps below make the following assumptions:
git
is used for version control.- The source code is hosted on Github.
However, the steps can easily be adapted to work with any version control system and code-hosting provider.
The (short) Steps
Here is an abbreviated version of the steps. They are arranged in the order they should be performed. Additional explanation is given in the next section:
- Make sure CI is succeeding on
master
branch. - Decide what the next version of the package should be based on the PVP.
- Update the
.cabal
orpackage.yaml
file with the new package version. - Make sure the
CHANGELOG.md
file has been updated with the differences between the old version and the current version. - Upload the code from the
master
branch to Hackage with the commandstack upload
. - Create a Git tag for the new version and push it to Github with the command
git tag v1.2.3.4 && git push --tags
.
The (long) Steps
Here is a longer version of the steps above.
Make sure all open pull requests on
Github
have been merged into themaster
branch.We are going to focus on the
master
branch for the following steps. The code in themaster
branch is what is eventually going to be released to Hackage.When making a new release to Hackage, it isn't strictly necessary to merge in all open pull requests, but it is generally a good idea to check just in case. If someone went through the work of adding a feature or fixing a bug they think is important, it is a good idea to make a release with their change in a timely fashion.
Make sure continuous integration (CI) is passing for the
master
branch.Before making a release to Hackage, it is a good idea to make sure all the CI tests are passing.
As of July 2018, I am using Travis CI to do CI for most of my packages. You should double check the build status of the
master
branch on Travis CI.For example, take the pretty-simple package. The build status of the
master
branch can be found at the following URL:https://travis-ci.org/cdepillabout/pretty-simple/branches
In practice, the build status of the
master
branch is usually determined by the build status of the most recent pull request. Since most releases are usually performed immediately after the merge of a pull request, all you need to do is check the build status of the most recently merged-in pull request.(Since most pull requests are only merged in if they pass CI, this step 2 isn't normally necessary. However, it is generally a good idea to take a second and check.)
Decide the next version of the package based on the PVP.
This is often the trickest step. Most Haskell packages have a version with the following format:
MAJOR1.MAJOR2.MINOR.EXTRA
. For example, given the packagefoo-1.2.3.4
, the MAJOR version is1.2
, the MINOR version is3
, and the EXTRA version is4
. The PVP page linked above gives rules for when each version needs to be bumped, as well as explaining why it is done this way.The explanations on the page linked above are somewhat hard to follow, so I recommend you look at the flow chart on the same page.
If you're still not sure which version component to bump, here are a couple rules of thumb:
If a change was made that the end user generally won't care about, it is safe to bump the EXTRA version. This includes adding documentation, adding tests, and refactoring (as long as it doesn't change the API).
For example,
foo-1.2.3.4
becomesfoo-1.2.3.5
.If new functions or types were added, you need to bump the MINOR version. The package should continue working for all existing users with NO changes to their own code.
For example,
foo-1.2.3.4
becomesfoo-1.2.4.0
.If existing functions or types were changed or deleted, you need to bump the MAJOR2 version. Existing users of the package may need to make changes to their code to work with the new version of the package.
For example,
foo-1.2.3.4
becomesfoo-1.3.0.0
.It may be worthwhile to announce the new version somewhere like Twitter.
If the package was radically rewritten, or really exciting new functionality was added, you can bump the MAJOR1 version.
For example,
foo-1.2.3.4
becomesfoo-2.0.0.0
.It would be a good idea to create a blog post about the new features and submit it somewhere like the /r/haskell or the Haskell mailing list.2
If you're still not sure which version component to bump, you should generally bump the higher component. For example, if you're not sure whether to bump the MINOR component or the MAJOR2 component, you should bump the MAJOR2 component just to be safe.
Users generally won't get mad at you for being too conservative.
You can look through the git commit log to figure out exactly what was changed from the previous version. You can also look at a git diff with the previous version.
For example, imagine we are working on the package
foo
. The previous version wasfoo-1.2.3.4
. There should be a git tag calledv1.2.3.4
. If you are on themaster
branch, you should be able to get a diff between the current code and the previous version with the following command:Update the
.cabal
orpackage.yaml
file with the new package version.If there is a
package.yaml
file in the current directory, you should bump the version number there.3 If not, then you should bump the version number in the.cabal
file.Make sure the
CHANGELOG.md
file has been updated with the differences between the old version and the current version.This is important so that users can easily figure out what has changed between versions.
Ideally, everyone sending in a pull request will add a new entry to the
CHANGELOG.md
. However, sometimes this gets missed. It is a good idea to make one last check before you release the package. Make sure to commit your additions to theCHANGELOG.md
before moving on to the next step.Upload the package to Hackage.
You should upload the code from the
master
branch. You can do this with the commandstack upload
orcabal upload
, depending on whether you are usingstack
orcabal
.4Create a git tag for the new version of the package and push it to Github.
The git tag should match the version of the package. It should start with a leading
v
.For example, given the package
foo-1.2.3.4
, you can create a tag and push it to Github with the following commands:
Conclusion
Except for figuring out the PVP version, following the steps above is not hard. However, since there are multiple steps, it is convenient to have a simple checklist to run through. Hopefully this blog post is helpful next time you are releasing a Haskell package to Hackage.
Footnotes
This idea is discussed extensively in the book The Checklist Manifesto.↩︎
However, this is definitely not a requirement.↩︎
I generally recommend you use
stack
, unless you personally dislike it.nix
is also nice, but I don't provide nix expressions for most of my packages.↩︎
tags: haskell