Tools available for hacking on free software projects have improved by leaps and bounds since the Bad Old Days of just a few years ago. However, there is still one process that seems to stink of aging. I'm of course, talking about the archaic process of packaging software for a release.
In practice, I find virtually every stage of maintaining my software smooth and reasonably well supported by the tools I use. I use good revision control processes and even better revision control systems. Github has in a short period of time done wonders for the projects I've migrated over to it, making it easier than ever for developers and contributors to watch changes as they happen and get their patches noticed, reviewed and applied easily. Even without github, a simple SVN/Trac setup did me well enough where I never felt significant pain while developing.
When nearing a stabilizing point with my mature software projects, I often will create a stable branch that indicates two things. The first is that the external API for the branched code will not change, so people can expect that code along any given stable branch is going to be backwards and forwards compatible. The second promise is that no code will be checked in that knowingly breaks something or creates instability that causes our tests to fail. Put another way, every patch that gets applied to a stable branch is in the interest of making that code more stable and solid. Usually, a stable branch means it's about time for a new stable release.
Why do we need releases again? Developers are usually running against the bleeding edge, and many contributors ride that wave as well, and power users will frequently at least build against the stable branches. The primary purpose of releases (not necessarily for everyone, but the reason why I do it) is to ensure that my software passes the 30 second test. This is essentially the idea that, if I've I'm a new user about to try a ruby reporting library called Ruport, I want to be able to do something like this:
gem install ruport
Once I've got the code installed, I want to promptly copy and paste some tutorial code that is interesting to me into my editor, run it, and see if it works. If it does, I'll look deeper, if not, I'll immediately hop back onto google and try to find something else that works. The only chance of me coming back to this code later is if I don't find something that passes this test, or if I find out later that I really need some of its features.
I tend to try really hard to make sure users can have this experience with my code, because I know this is how some people pick their tools and libraries. Package managers aren't a bad thing, so the idea of releases themselves are not the problem.
The problem I see are that we've been building tools to map the way we organize our code in revision control systems, or on our local filesystem, to the way we package and distribute code. Why can't we invert this relationship?
In Ruby, you could use Hoe to simplify the deployment of your code to RubyForge. You could also take advantage of the fact that Github auto-builds RubyGems for you. But this only makes the problem less of a hassle, it doesn't get rid of it entirely.
What I'm suggesting is that in order to really make 'releases' match up with the way we develop our software, it might require our package managers to become revision control system aware, not the other way around. To me, it feels like branches and tags are the 'real' natural way to work with code, and that version numbers are just a convention left over from when we needed to read a static file of release notes to figure out what is going on in new versions of packages we use.
Here are some examples of things I'd love to be able to do:
I'd like to be able to just specify a repository location directly to my package manager, (optionally identified by a label)
gem source rinara git://github.com/ruport/ruport.git
When I install the package, I'd like to be able to specify a branch of the code
gem install rinara:ruport -b stable-1.6
This would then pull down the very latest code in the stable-1.6 branch, since it's likely to be 'more' stable than an officially packaged release.
If I leave out the label, and the package is ambiguous, I want it to tell me:
$ gem install ruport Please select your package:  rinara:ruport  rubyforge:ruport
I want the following to grab me the very latest code (basically the bleeding edge):
But I want to be able to specify a branch, too:
gem "ruport", :branch => "stable-1.6" require "ruport"
I want to be able to do the same with tags:
gem "ruport", :tag => "teh_pretty_kittten"
And if the project follows a standard convention of tagging release numbers, I want to be able to just use that:
gem "ruport", "1.0.0"
I'm sure I can think of more things, but I'll stop here in hopes that people see where I'm going with this. Even though I'm talking in the context of Ruby, I'm really thinking about all package management. I feel like release maintenance is a headache that most of us avoid by hacking together deployment scripts to work around our outdated systems rather than working on putting together systems that work as we want them to.
I think it'd be a huge step forward to see tight integration between popular revision control systems and popular package managers. I haven't done much research into this to see if efforts have been made, but then again, I haven't seen any blindingly obvious solutions to the problem that have been generally suggested just yet, either.
What do you think? Do we need to update our notion of 'released packages' to match our increasingly sleek revision control tools, or am I just whining about a problem that already has been solved in a 'good enough' fashion?
I'd especially be curious to hear about projects that address the problem, or people's general thoughts on what's needed to bridge the gap between 'released code' and 'code under development'
Let me know what you think.