This blog post is a cross post from
a guide I wrote on the Commercial Haskell Github account. That
URL is the authoritative location for this document. If you want to
send any updates and recommendations, pull requests certainly
welcome!
Maintaining an open source project is not trivial. It requires
not only technical skill, but also social and time management
skills. Finding the balance between helping others contribute
versus implementing changes yourself, or between being helpful and
being a slave to your project, is tricky. And worse yet: it’s
non-obvious when starting an open source project that these
problems even exist! The goal of this guide is to elucidate this
topic, and clarify options.
This guide is obviously non-binding in any way: anyone is free
to maintain their project in whatever way they wish. But hopefully
this guide will make it easier to maintain a project. Finally, this
guide is itself an open source project following the guidelines
below. In particular:
Maintenance level: dedicated
Accepting maintainers: yes, request via PR
Maintenance level
By making something open source, you are not giving any
guarantees to users of the software of any kind. However, some
people may expect certain levels of maintenance unless told
otherwise. To avoid confusion and frustration on both the user and
maintainer sides, it’s a good idea to define your maintenance level
explicitly, in the project’s README. Here are some suggested
“standard” levels you can reference:
-
Abandonware: this code is available as-is, but
the author has no interest in it. If you find a use for it, great.
But don’t expect PRs to be merged, or issues to be responded
to.
-
Interested: the author has some interest in the
project, and may merge PRs/respond to issues. However, don’t expect
much.
-
Happy to merge: the author will review PRs and
merge good ones, but is less likely to respond to issues
-
Dedicated: the author will strive to review PRs
promptly, and get back to issues in a reasonable timeframe, usually
within a week. Of course, real life has its own demands, and
vacations happen, so the timeframe may be delayed.
-
Highly supported: there is a dedicated team of
maintainers working to keep this project running smoothly. PRs will
be reviewed and merged very quickly, and issues should be responded
to within 48 hours, barring unforeseen circumstances.
In addition to these levels, it’s also good to specify whether
people can request that they be added as maintainers as well. This
could look like:
-
No: not interested in having other maintainers
on the project
-
Yes, request via PR: if you send a few good
PRs, and say you’re interested in being a maintainer, you’ll get
commit access
-
Yes, request via issue or email: specify a
contact method, and what the requirements are to get maintainer
status
Again, these are just suggestions, and you can of course define
your own level (or leave this alone entirely!).
Use standard contribution tools
You should make it as easy as possible to contribute to your
project. And this means you should use standard approaches
whenever possible, for two reasons:
-
People have already learnt these approaches. Even if your new
approach is better, do not underestimate the resistance people will
have to learning something new! This isn’t stubbornness on anyone’s
part, it’s a natural defense mechanism against needing to learn
thousands of variations on the same theme.
-
Standard approaches have been battle-tested to solve common
problems people run into.
Here are some things you should consider:
-
Put useful information into a README.md file in the root of your
repo. In addition to information on how to use your project, it
should give some pointers on how to contribute, even just as a link
to another document. Make sure to include:
-
A list of project goals, to hopefully clarify whether a certain
feature fits in with the project or not.
-
The maintenance level, mentioned above.
-
Any information about how you like to receive PRs. This can be
highly opinionated, and provided as a link. Here’s my highly
opinionated guide:
https://www.snoyman.com/blog/2017/06/how-to-send-me-a-pull-request
-
If you’re using Github or similar, provide issue and PR
templates to help people file useful issues and complete PRs. As
one point of reference, see Stack’s .github directory: https://github.com/commercialhaskell/stack/tree/master/.github
-
If you care about consistent styling, be sure to include a
reference to the style guide.
-
Add CI scripts that enforce what you care about. It’s much
easier for a contributor to fight with Travis or AppVeyor than to
have a higher-latency back-and-forth with the maintainer. CI can be
used for styling, linting, and much more!
Responding to issues
This ties in directly to the maintenance level. What I’ll
describe here is the ideal goal to strive for. But keep in mind
what we discussed earlier: you’re not a slave to your open source
projects, and have the right to say “I’m not going to deal with
this now, or ever.” But please consider being upfront
about such a decision!
-
Triage quickly. If new issues come in, have a standard triage
process, which will include:
-
Labeling the issue
-
Asking for more information (ideally, have a standard issue
template that requests the most common info already)
-
Telling the issue reporter that it’s being looked into
-
Define an owner, who is responsible for driving an issue
forward. This is vitally important on multi-person
projects. It’s too easy for issues to remain in limbo because no
one knows who’s ultimately responsible for making a decision.
- On Stack and Stackage, we’ve found a great approach is to have
a team of people take turns being “on call” for initial triage, and
to pass off issues to others when necessary.
-
Define clear steps to closing the issue. It can be frustrating
for everyone involved if there is no way to move forward. Get a
reproducing test case, say “if this passes, we’ll close the issue,”
etc.
-
If issue filer unresponsive, close it. There is limited time in
everyone’s life, and limited energy in the universe. Unnecessary
open issues clog up people’s mental capacity. If you don’t hear
after X amount of time, close with a comment “closing due to
unresponsiveness.” Ideally, explain this in the README or
contributor guide; it’s not a personal slight, it’s just official
policy.
Say no when appropriate
You will receive feature requests and pull requests which don’t
fit the project’s goals. You’ll receive poorly written PRs. It
helps no one involved to drag out the process if you know this will
never be worked on. Say no upfront, ideally explaining why. If
there’s a possibility to fix the request/PR, leave it open. If it’s
inherently mismatched, close it out. (But please don’t
mute the conversation, that’s rude.)
Related to this: encourage contributors to open up issues before
submitting large PRs. A large PR adding a feature that won’t be
accepted is frustrating for everyone involved: contributors wasted
their time, and maintainers hate turning away work. Better to have
a design phase. (I mention this in my opinionated PR guide.)
Labels issues for newcomers
Be sure to label issues that you think a newcomer will be able
to work on. It provides a gradual onramp to understanding the code
base, and getting PRs merged is a dopamine hit for everyone
involved. Resist the urge to knock out the easy issues yourself!
You will spend more time helping a new person with
an easy issue than doing it yourself, but it’s an investment in
their future, as well as your project’s.
Opinionated recommendation: be free with the commit bit once
people prove themselves, they rarely abuse it, and you can always
revert something bad. I typically give out a commit bit (if I
remember to) after 2-3 successful PRs. (I think this was originally
advocated by Edward Kmett.)
Encourage contribution
Whether explicitly in your README, or implicitly with how you
communicate, you should try to motivate people towards wanting to
contribute. There is little glory in day-to-day maintenance of an
open source project. You should give people getting involved as
much in the way of positive reinforcement as you can. Ideas
include:
-
They will be able to hone technical skills
-
They will get access to mentorship from someone with more
experience (see below)
-
They will be empowered to fix problems that are hurting their
work, instead of being blocked on an upstream maintainer
-
It can work as resume building. Note that, unfortunately, some
employers are not incredibly interested in FLOSS
experience. But many others do weigh such activities heavily.
Offer mentorship when possible
When you have the time and inclination to do it: make it clear
that you’re available to mentor people through issues. Make
yourself available on something like IRC or Gitter, as people
prefer live chat to the (perhaps more intimidating)
communicate-via-Github-issue route. Make it clear: you won’t be
facing the wolves alone!
Increase the bus factor
The above leads directly into the bus factor. For those unaware,
the bus factor is how many people need to be hit by a bus before
your project dies. In addition to spreading knowledge and
enthusiasm about your project, please be sure that:
-
At least one other person has commit access to your repo if
you’re gone, and upload access to wherever your project is deployed
(e.g. Hackage).
-
Set up a fallback plan if you aren’t available, either short
term or long term. Consider having an open
source will
-
Ideally make sure others know the code base well enough to
maintain
Difficult users
This is the most depressing part of the guide, which is why I’ve
left it till the end. There will ultimately be people who interact
on an open source project in less-than-ideal ways. Figuring out how
to respond to them is difficult to say the least. By identifying
the behavior, and having standard responses, I’m hoping to be able
to depersonalize it a bit. Furthermore, perhaps by writing this
down, those interested in participating in open source will learn
some behaviors not to demonstrate themselves.
Poor bug reports
This one is all too common. Writing a perfect bug report is
hard. You need to figure out all of the context you need
to provide, without providing a wall of text. If you err on either
side (too much or too little), you’ll waste somebody’s time.
Figuring out the balance is hard. If you’re new to reporting
issues, explain as such, and be open to getting asked to rephrase
the bug report and significant constructive criticism.
Keep in mind: you’re asking for help from someone, your goal
should make it as easy as possible to provide that help.
XY problem
I won’t waste time on redefining the XY problem, Wikipedia defines it
well, plus a good thread on Stack Exchange.
The XY problem is usually a direct result of trying to be
respectful of people’s time, and not bore them with “unnecessary”
details. Unfortunately, in the XY problem, it often backfires.
There’s no sure-fire way to completely avoid it. If you’re
trying to figure out how to concatenate two strings, you don’t need
to give a backstory on the business goals of the app you’re
writing. By contrast, if you’re trying to read a file into a
textual value, and have figured out how to read it as a binary
value, don’t ask “how do I convert a binary value into text?” Most
likely, the broader scope will reveal better answers.
Help vampires
I believe the term was originally crafted by Amy Hoy in the blog
post Help
Vampires: A Spotter’s Guide. Again, I’ll pass on redefining the
term here, as that blog post does a great job of it. There’s a
difficult line to walk when dealing with help vampires. On the one
hand, you want to foster a community where people are able to ask
questions and help each other. On the other hand, a non-stop
onslaught of tedious questions with no end in sight can crush the
spirits of contributors.
I can’t say that I have a perfect answer to dealing with help
vampires. Education about the problem is great, but by their very
nature, the help vampires are least likely to see the educating
material. Ultimately, it seems like there are two ways to deal with
the problem:
-
Ignore it and let it fester. Contributors may end up offering
help to the vampire, get sucked dry, and lose momentum on the
project. Alternatively, no one may answer the help vampire, giving
the project the (unfair) appearance of being unhelpful to
struggling users.
-
Address the problem head-on, and explain that the person in
question needs to take more responsibility for solving their own
problems. This is harder to pull off, but ultimately is worth it.
Here’s a sample wording paraphrased from a real-life example:
This doesn’t sound like a bug or soluble issue for the project
maintainers. Instead, this sounds like a request for consulting or
assistance. You might try an IRC channel or a Slack community to
see if someone can help you.
I mean this with no malice: Please keep the issues you file on
GitHub limited to actionable issues for the people working on the
project. We’re here to improve the project. We cannot provide help
with open-ended project work. We are here to work on stuff that
helps all users of the project. If I fix a bug, that helps me and
helps everyone else using the project. If I help you with a
specific, non-project-related issue, that doesn’t help any other
users users. I understand you probably didn’t know this as a lot of
these norms in open source are unspoken and unwritten, so I’m
trying to lay out some of it so that you understand better going
forward.
Entitled complainers
Some users feel that they are entitled to some kind of solution
for their problem. Part of the goal for maintenance level is to set
these expectations correctly. As a semi-concrete example, imagine
that operating system XYZ seems to behave differently than many
other OSes. You don’t use XYZ, and you’re not particularly
interested in herculean efforts to make your project work for it.
You may receive a stream of complaints
requesting/insisting/demanding that you look into these issues.
Set expectations. State in the README that there are known
issues with XYZ. Explain that it requires more effort to support
that configuration than you have. And if you’re not inherently
opposed to XYZ support, mention that having a contributor on the
team take responsibility for XYZ support will help significantly
with getting it better maintained.
Subscribe to our blog via email
Email subscriptions come from our Atom feed and are handled by Blogtrottr. You will only receive notifications of blog posts, and can unsubscribe any time.
Do you like this blog post and need help with Next Generation Software Engineering, Platform Engineering or Blockchain & Smart Contracts? Contact us.