Video

Want to see the full-length video right now for free?

Sign In with GitHub for Free Access

Notes

We have a previous episode about how to contribute to open source. Now, let's talk about maintaining open source projects.

One big change is that the project has a community that the maintainer is now responsible for managing and replying to.

Replying to an issue

At first, you might be happy that issues are being reported: each issue means someone is using the project! But the issues and pull requests can become overwhelming. What do do?

First of all, "Sorry, I don't have time to respond right now" is a much better response than not replying at all. It builds trust. It means you're being authentic about your availability, and the submitter is acknowledged. They know that the maintainer has seen their issue. And from you, the maintainer's side, you're relieved of the pressure of replying to their post. GitHub's saved replies feature can help a lot.

Providing people with immediate thoughts, or a small suggestion, can also help a lot. As the maintainer, you have more context and can guide people towards a solution even if you don't know the exact solution right away.

High volume of submissions

At first, every issue should be discussed in the issue tracker for visibility. But when the volume of submissions get high, and a community starts to form, try using Stack Overflow. When other (non-official contributors) start answering questions, that's a sign that you've outgrown GitHub issues for some things.

Of course, the community must be large enough to sustain questions that are not answered by the maintainer. But once you hit that point, moving off of GitHub issues is a good idea.

Unable to reproduce an issue

Paperclip is a good example of a project with a lot of moving parts (deployment environment, image post-processing, Ruby version, Rails version, etc) and so reproducing issues is harder. The Paperclip maintainers have a saved reply that links to http://yourbugreportneedsmore.info/, which explains how to report an issue in such a way that maintainers will find it useful.

Empathy as a maintainer

Some of the actions of a maintainer might come off as a little hostile to contributors. For example, closing an issue without explanation is definitely going to be interpreted as an unfriendly action. GitHub's saved replies are great for this -- you can write friendly, comprehensive saved replies on Sunday while you're rested, and use them on Tuesday when you're in a rush.

Issues that could be Pull Requests

Some issues are so detailed in their description that they can be pull requests. Both parties benefit if these issues are turned into pull requests instead: the maintainer has less code to write, and the contributor gets credit for committed code. Everyone can write a pull request!

Recurring questions

You might have answered the same question five times. That means that the documentation is lacking. If it's particularly common, consider putting it in the README, not buried in the docs for the code. One example of this is capybara-webkit. It depends on Qt, which is not immediately obvious, so the capybara-webkit README mentions this at the top of the README.

Pull requests that don't belong

Sometimes a pull request doesn't fit with the project. Maybe it doesn't match the long-term goals of the project, or it's being fixed in a better way elsewhere. Whatever it is, rejecting a pull request is awkward: someone invested time in figuring out the code and writing their pull request. Rejecting the code is hard! How and why to say no is tricky. For example, maybe something is correct, but is a configuration that you don't use, so you can't safely maintain it. (In that case, providing an extension mechanism is probably the best route, so that people can hook into your code and make it work with their configuration.)

Encouraging new contributors

It's worth encouraging people to open issues, or open small PRs. Those will start a conversation, and you can cut it off early rather than making people do all the work to write a full patch that might be rejected.

Commit messages

The code is important, but the Git history is just as important. Tute rewrites Git history a lot. A small feature might have 15 commits that really led to one realization and are better as 1 squashed commit that fully explains why the change was made. Larger features might require more than one commit, but each commit should still be atomic and cohesive. Reading the commits in order should make sense and explain why the pull request's change is being made.

It's fine for the maintainer to squash commits from other people. The maintainer will be listed as the committer, but the contributor will be listed as the actual author of the commit, so they still get credit for their changes.

Keeping a high-quality code base

At thoughtbot, we care a lot about quality. We want everything to be clean. Once the codebase or tests start becoming lower-quality, they are more likely to remain lower-quality in the future. Keeping everything high-quality (code style, passing tests, high test coverage, etc) means that contributors will provide higher-quality code, too, because they will take their cues from the codebase. Using automated services like Hound CI helps a lot: by the time you look at the PR, Hound has commented and the contributor has fixed issues. It's a nicer experience for everybody.

Documentation

Documentation is very important and will save time for everybody involved in the project. The README is the onboarding process and landing page for your project. It tells people what the project is, why it exists, and how to use it. The Redux project does not have a lot of code, but it has tremendous documentation, and it's definitely helped the project become popular.

The NEWS file is an important file. It lists the user-facing changes (not just the commit log), ideally organized by version. The Paperclip project has an excellent NEWS file. It's more important the larger the project is, because so many more things can change and break between releases.

Open-source projects should also have a CONTRIBUTING.md that tells contributors how to contribute: how to run tests, what the style guide is, goals for the project, etc. GitHub will automatically display the CONTRIBUTING file when making a new pull request, so putting effort into the CONTRIBUTING.md is well worth it. Paperclip's CONTRIBUTING.md is worth looking at.

Licensing your code

Legally, if you publish your code without a license, it's not actually free software. Free software projects should use free software licenses. thoughtbot uses the MIT License. GitHub runs Choose a License, which makes it straightforward to pick a license that fits your code.

You can also dual-license your code with a copyleft license (which requires that the code be given away free) and a commercial license. People who want to use the code for commercial purposes must use the commercial license (and often pay you) while other non-commercial entities can use it for free. It helps you sustain your project by bringing in some money. Sidekiq is dual-licensed.

Versioning

Semantic versioning describes how to assign meaning to a version number: How does version 1.0 differ from version 0.8? 1.2.3 versus 1.2.1? 2.0 versus 1.0? The Ruby community generally follows strict semantic versioning.

Semantic versioning follows a three-part MAJOR.MINOR.PATCH versioning scheme. You should increment the:

  • MAJOR version when you make incompatible API changes,
  • MINOR version when you add functionality in a backwards-compatible manner, and
  • PATCH version when you make backwards-compatible bug fixes.

Rubygems' pessimistic ~> operator is helpful when using gems that follow semantic versioning.

Security and critical bugs

A critical bug is one that must be fixed because the project won't run for some group of users. A security vulnerability is one that makes the project insecure. When working on a security vulnerability, don't work in the open and don't announce it. When it's fixed, announce the vulnerability, announce the fix, and encourage people to upgrade.

Further reading