Open Source Preflight Checklist
About this checklist
So you want to open source some code? Great! Here's a few things you can do to make sure the launch goes off the best way it can.
This is a guide of sensible defaults for a company setting (call them "best practices" if you really want), not hard rules. If it makes sense to do something different, then feel free to. The goal of this document is to make some of the boilerplate bootstrapping decisions and tasks easier so we can get more high quality open source projects out the door that can take off and fly on their own.
For convenience we’ve given specific examples from the Ruby ecosystem (
gem etc.) but this guide applies equally to other tech stacks.
Where possible we'll try and talk about this in terms of concrete text and code changes you can make to your project.
If you want the TL;DR version, skim down for all the Action blocks of text and just do them.
If you want the really long version of all this, go have a read of Producing Open Source Software by Karl Fogel. It covers all of this and more.
Before you start
Releasing open source is like having a baby. Even if it's accidental, and not entirely planned, you are still responsible for feeding it, clothing it, housing it, helping it grow, and keeping it healthy - and if you aren't able to do that down the track for whatever reason, it's up to you to find someone who can.
We want healthy open source projects that are maintained throughout their useful life. It's a big responsibility, if you're OK with that, lets go!
Real world example of these guidelines
If you want to see how this document translates to the real world, check out the
Rack::ECG project. It was created in parallel with this document specifically to flesh-out these ideas and write them in a TDD kind of way to make sure they are realistic and not too onerous on new projects.
Choose a good name
Pick something obvious that is related to the project purpose in some relatively obvious way. Puns and joke names are OK, but don't make them too obscure, and remember there are a lot of non-native English speakers out there, so don't rely on deep cultural knowledge to make them work
Make sure it is googleable, and doesn't get crowded out by other common words when people search for it.
Ideally think about how easy it will be to get a twitter/facebook/domain name/whatever down the track.
Pick a name that isn't in use by other open source projects already. If it's in a totally unrelated technology/area, and the name is really awesome... then maybe duplicate it, but avoid if you can.
Make sure the name is available on rubygems/npm/hex/cpan/whatever package manager you will need to use to distribute it. Often common names are taken, even though they're not used actively.
And it goes without saying that you should avoid anything offensive or discriminatory.
- create a GitHub repo for your project
- create a
README.md file in your project if it doesn't exist. Put the name in the first line
Have a clear mission statement
Think about why your project exists. There is obviously a reason. You may have written the code from scratch or extracted it from an existing internal application. What problem does it solve and for who? Why does it exist?
Distil that down into a couple of sentences. Make that your project's description on GitHub, and in your README.md
Also, make sure not to call it a "Mission Statement". Developers hate that kind of thing :wink:
Action - Add your mission statement as your GitHub project description (maybe shorten it a bit if it's long) - Add your mission statement as the second line in the README.md file
Focus on your features
Nail down what your open source project does that is useful. Be specific about it. This should build on your mission statement, and show exactly why users should care about your project.
This is one of the first things potential users/contributors will look at, and it's your main chance to really sell the benefits of your project.
- write a bullet list of features. Add it as the third thing in your README.md after the description under a
## Features heading
Let users know your development status
Include a "Development Status" section. Be honest about it. If it's still early stages, and you are still feeling your way around, tell people that. If APIs are in flux, and features are still stabilizing or are missing - users are generally OK with that if they know what they're getting into as early adopters.
Likewise, if your code is solid, and ready for production use, tell people that too. If it's ready to carry the load and be really useful, we want people using it and getting value from it!
While you're at it, set up an automated CI build, and publish that with a widget. Travis CI is a good and easy place to start.
- add a
## Development Status section to your README.md
- be honest about it. Don't oversell what you've got, but don't be shy about it
- set up build status reporting through Travis CI
Make it easy for users to get started
Say how you install your library. If it's a gem, say how to add it to bundler, and how to install standalone.
Then explain how to set it up and configure it.
Most importantly, show a few basic use cases straight away. Try and show evidence of value to the users. If it's a library, show input/output/effects via code snippets, and log output.
In addition, you can include more complex example code in an
/examples directory as part of your code base. Showing off more complex, fully executable code is a great way to show users what your project can do without crowding the README.md file
Action In your README.md add - how to install - how to configure - show the main features in short, easy to understand examples
Figure out your communication channels
Obviously you've got your GitHub page.
If you setup gitter, be sure to add GitHub and Travis CI integrations to automatically post details of activity.
Remember - having a real time chat room means someone actually needs to check on it, and respond to conversation there.
Action Include links to - GitHub project page - gitter IM chat (if you are actually going to be in the chat room, and respond to conversations there, no point having it otherwise). - GitHub issues - maybe a mailing list
Decide on project owner
Successfull projects need solid leadership. In the early days, that's pretty much all there is - one or two developers hacking on it, so it's easy to ignore it. However, as the project grows and contributors join, you'll need a way to make sure you're heading in the right direction and following the vision for the project.
The simplest way to do this (and the way most projects start) is to default to a benevolent dictatorship. Figure out who that benevolent dictator is. Make sure this is stated in the README under a
## Maintainers section.
Everybody was sure that Somebody would do it,
And Anyone could have done it
But in the end Nobody always ended up with the task.
...So, because anyone can do it, it's likely nobody will do it.
Choose a single person, who will own the project and take responsibility for it.
It's OK to have a team of maintainers if multiple people will be working on the project. Add them to the README under
## Maintainers too. However, have one person who owns the project.
Once you've got a specified owner - that person needs to make sure PRs get reviewed and merged/closed, bugs get fixed, and features implemented. The owner doesn't have to do all that themselves (although they quite often will), but the need to make sure it happens by delegating, bugging, or begging others to do it.
Remember too, that the owner needs to think about who the project is handed over too if they aren't able to work on it anymore. People leave, people change teams and focus, things happen. When they do, gracefully hand over the project. But this is open source, right? So even if you leave the company/team etc, you can still keep working on it. That's one of the awesome things about open source.
- decide on an owner
- add their name to a
## Maintainers section in the README, saying they are the owner. Add their real name, and a a link to their GitHub profile (e.g: Julian Doherty )
- add names of other maintainers too if there are multiple people regularly working on the project.
Pick a license (just go with MIT)
You need SOME license. If you have none, then the project by default ends up in the public domain with ambiguous copyright, and that means technically no one else can modify it.
Go with MIT. It's short, simple, widely used, and most often fits with the way we want people to use your code. If you bootstrap a ruby project using
bundle gem my_awesome_gem, you get MIT by default.
- just use MIT
- add a
LICENSE.txt file to your project containing the text of the license.
- add a
## License section to your README saying what license you are using, and linking to the
Add an explicit code of conduct
There are so many good reasons to be inclusive and open, and to be explicit about being so.
Contributor Covenant is a quick and easy way to set this up. Just copy and paste a code of conduct into a
CODE_OF_CONDUCT.md file in your project.
State this in your README.md and link to it.
Actions - add a code of conduct. Contributor Covenant is a good place to start - link to it from your README.md
Think about how you will handle contributions, tell people about it
If you build a gem with
bundle gem my_awesome_gem, it will automatically add boilerplate to your README.md. This can be OK, but have a think about whether it's appropriate. Particularly around if you want to encourage whole massive new features from out of the blue. If you don't say otherwise, then they will happen. And it's entirely possible they won't be in line with your project vision, and you'll either need to reject them, or have them heavily modified before accepting them.
This makes for sad contributors who have burnt a lot of energy, enthusiasm, and good faith, who may never come back. And more work for you to clean it up.
It can be better to be clear around how each type of contribution is handled:
- bugs, small changes etc: just fork, and send a PR
- features: advise the contributor to make contact with the project first (either via issue/chat/mailing list etc), and discuss it first so they aren't wasting their time going in the wrong direction. Then do a PR.
The following might be more appropriate:
# Contributing For bug fixes, documentation changes, and small features: 1. Fork it ( https://github.com/[my-GitHub-username]/rack-ecg/fork ) 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Commit your changes (`git commit -am 'Add some feature'`) 4. Push to the branch (`git push origin my-new-feature`) 5. Create a new Pull Request For larger new features: Do everything as above, but first also make contact with the project maintainers to be sure your change fits with the project direction and you won't be wasting effort going in the wrong direction
For larger, more established projects with more complex processes, you may wish to add a separate
CONTRIBUTING.md doc. http://contribute.md/ has a good starter template if you wish to do that.
- add a
## Contributing section if it doesn't exist already
- add details about how you want to encourage contributions to the project.
Have tests. Make it easy for contributors to run them. Hook them up to Travis CI so they are automatically run.
- have tests (you do this already, right?)
- make them easy for contributors to run. Ideally as default
rake task or equivalent
- automate them with Travis CI
Once you have done everything, and you are ready for launch, it's time to package and distribute.
Make sure you have properly filled out the
my_project.gemspec (or equivalent) file with appropriate name, description, authors, license etc.
Set up the project on rubygems or equivalent.
You'll also need to figure out who else owns the gem on rubygems (or equivalent) and set them up with access to push the gem as well. See gem owner for more details on how to do that. You don't want to be the only person able to push a gem, then get bugged by other maintainers while you're diving in the Caribbean 6 months after you quit to go travelling the world to push a new gem version (yes, that actually happened).
- make sure packager config files are complete
- :shipit: SHIP
gem owner to set up ownership (or equivalent)
Haha, no. This is just the start :grinning:
The fun starts once your code is out there, people start using it, start depending on it, and then start hating you for it ;)