Samus Helps You Publish Your Open Source Software
Today I’m announcing Samus, a project I’ve been working on over the last few weeks that helps you automate many of the repetitive tasks involved in releasing code. Inspired by real-world events, Samus simplifies things like bumping your version, tagging your commit, pushing your changes, cutting a gem, and more. It operates via a manifest file which contains simple and discrete actions to build and publish your code. Samus knows how to clean up a failed build, and can do sanity checks to ensure everything will succeed when you finally hit the big red button. Samus is also used to publish Samus, so you can use its generic manifest in your own Ruby projects.
There are a couple of problems I’m trying to solve with Samus. I noticed these problems when releasing versions of other OSS projects I maintain
- Automate the obvious release-time tasks like bumping your library version, adding a version tag, building the RubyGem, and more. Although tools like
npmhave language specific ways to handle some of these things, Samus gives me a generic solution I can use on pretty much all the code I release, from C, to JS, to Ruby code.
- Simplify credential management so that you know your machine has the right keys before you try to push code. I release code from different machines. I usually have Git setup on these machines, but API keys for package managers is occasionally a different story. Samus allows me to share credentials in a way that is as secure as I need it to be
- Package an archive of the release so I can batch releases. If I’m doing a release of multiple libraries at once, I usually want them all staged before I push them out. Having a separate “stage” step lets me make sure everything is ready and working before I start a release. More on this at the end of the post.
Here’s a simple example of how I published Samus, today:
First, I created a file
~/.samus/personal/credentials/lsegal.rubygems with my RubyGems access key. The contents of the file are:
Samus looks inside
~/.samus for custom commands and credentials. The sub-directories can be local-only directories, or they can be Git-backed (and optionally private) repositories that I can share with other maintainers. Organizing this is mostly up to you, so there is a lot of power here.
Next, I ran
samus build 1.0.0, which used the samus.json manifest file to run the tasks needed to build the release-v1.0.0.tar.gz file.
Finally, as the last step, I publish with:
samus publish release-v1.0.0.tar.gz.
That’s it. In short:
mkdir -p ~/.samus/personal/credentials echo "Secret: API_KEY" > ~/.samus/personal/credentials/lsegal.rubygems samus build 1.0.0 samus publish release-v1.0.0.tar.gz
Why Separate Build & Release Steps?
One big change from the normal work flow is separating “staging” a release from the release itself. Typically, when you release code, you go into your project, update version, build the gem, push code, and push the gem. This all happens from your workspace. Although this works for a single project, it does not work quite as well when you are releasing multiple versions of the same project (like, say an RC candidate and a stable release, or multiple libraries that depend on each other) at the same time. A lot of build time tasks can take a while, like running test, building docs (if necessary), occasionally compiling code, so if I’m going to release multiple things at once I want to make sure everything is good to go before I hit the button. It’s sort of the same way “git commit” and “git push” are separate tasks. You often want to make sure everything is setup locally before you “push-to-live”.
That said, Samus could very well include some simplistic “build-and-push” single-command syntax, if it were useful.
Samus TODO & Contributing
Although Samus is designed to be a simplistic tool, there is still a few extra features it could use. Here are a handful of ideas:
- Samus could use more build and publish commands. For example, a command to update your changelog at build-time, more control over Git workflow management, and integration with more package managers (only RubyGems and npm are currently supported) would be great.
- Improving the credential management to support different setups. Currently Samus does rely on SSH keys being available on the machine for Git commands. I would like to fix that.
- Self-contained releases could be useful. Right now you still need some local setup to use Samus, like credentials on your machine, and occasionally some binaries (custom commands, if you use them). Being able to build a self-contained archive with all the custom commands and credentials in the zip would make publishing much more reliable (though a little less secure if that archive got leaked).
Extra commands are always welcome, so if you have an idea for a generic command, feel free to submit a pull request to have it included in Samus.
If you think Samus would be useful, feel free to give it a spin and let me know what you think. I just updated YARD to use Samus by adding the manifest file in the Quick Start above– for most Ruby projects, this would be enough to get you started.