Shot of a group of university students working on computers in the library at campus
Community

How to Create Good Good-First-Issues

A good-first-issue, as you probably know, is a GitHub issue or pull request that has been marked by its creator as appropriate for beginners. Typically, it’s also given a good first issue label, making it easier for newcomers to find, although some projects use terms like easy-fix, beginner-friendly, or low-hanging fruit. good-first-issues

However you label them, good-first-issues are very much worth creating. They help attract contributors who are new to your specific project and to open source in general. There’s both a selfish and an altruistic benefit here. By signaling that your project welcomes beginners, you make it more approachable to newcomers and even people with experience who might just want a better sense of what you are doing. That increases the chances that they will stay on as contributors, thereby helping you grow your community in a more organic and sustainable way. At the same time, you are inviting into your open source project people who otherwise feel excluded from open source in general. This helps increase the diversity of your contributors.

It’s possible, though, to write a better or worse good-first-issue.

In this post, I’ll offer some ideas, based on my own experience, for creating good good-first-issues on GitHub, along with a few things to avoid. All of my examples, by the way, come from the Tern inspection tool project which I co-maintain. Other projects have their own approaches to good-first-issues and might even avoid them altogether for perfectly legitimate reasons.

First off, you need to lay the groundwork for creating good-first-issues. That means ensuring that your project is ready to accept pull requests by adopting or creating your own versions of:

  • README, CONTRIBUTING, LICENSE, NOTICE, CODE_OF_CONDUCT files
  • GitHub’s Issue Template
  • GitHub’s Pull Request Template
  • Getting Started tutorials (you are welcome to use mine as a reference)
  • Appropriate tests for code review: linters, unit tests, functional tests etc.
  • Continuous integration tools (Tern uses CircleCI and TravisCI; GitHub Actions is still valid)

You don’t need all of these in place at once, but each one of them helps. And collectively, they signal that you are willing and able to accept pull requests and will be able to process them appropriately.

Now it’s time to create some good-first-issues. One way to do this is by breaking down features you’d like to see added to your project into small tasks. So, for each small task, you create a feature, and the smallest of them are natural good-first-issues. Of course, you can also create good-first-issues that fix bugs as they turn up in the features you build—and the same basic rules of good-first-issue making apply.

Once you’ve filed a good-first-issue task, you need to document it. You’d be surprised by how many issues labeled as perfect for newcomers turn out to assume that the newcomer is already familiar with the project and therefore aren’t fully documented. Ideally, you’ll include the goal of the task, offer some reference code and add a reference implementation. That provides beginners with immediate access to everything they need to complete the task. And it helps avoid putting contributors in a position where they are afraid to submit something for fear of doing it wrong and inviting some sort of backlash.

GitHub’s “issues” page has a useful button that will give you results for a search on a label named good first issue. Creating a label with this name allows contributors to easily find these issues. Taking advantage of this functionality improves the contributor experience.

Stubs are a good way of creating placeholders in your code for features that are yet to be implemented. This allows for multiple contributors to work on your code independently without interfering with each other.

It’s also worth picking issues that add to the most modular parts of your code. Avoid referring to “spaghetti code” areas of your project as these can be overwhelming to new contributors. Instead, choose a part of the code that has looser coupling to the critical parts of your code.

Don’t be afraid to make at least some of your good-first-issues super easy to complete. In some cases, I have actually copied and pasted the piece of the code that I want changed and stated precisely what I wanted the contributor to do with it in the issue itself. That allows very new contributors to focus on getting familiar with the process of submitting a pull request rather than trying to solve the code. After all, open source contribution is not a technical interview. New contributors are also new to using tools like git and GitHub. Maintainers who understand that can offer valuable avenues to learning. When people get comfortable with the steps, you can give them something a little more challenging.

Sometimes my good-first-issues haven’t worked so well. I’ve ended up writing good first issues that were dependent on other good first issues, for example. That led to my working with too many contributors who all had to work with each other without knowing each other, which in turn placed a burden on the maintainer (i.e. me) to try and schedule work that was moving at different rates of completion. In a situation like that, it’s fine to go back to someone and say “actually, I need this done sooner, so can I please give you something else to work on?” But you can’t insist that they follow your timeline—you need to offer issues that they can complete in whatever time they have available.

I’ve also had problems when I’ve not properly documented an issue (see above), or when I’ve picked tasks that I really should have been dealing with myself. These have tended to involve issues that require abstractions or architectural decisions that only a maintainer has a sufficiently broad perspective to make. So, they were my responsibility to resolve.

But overall, when we have taken the time to deliberately create issues that people can approach without feeling judged or overwhelmed, we’ve successfully managed to attract and maintain contributors to Tern who don’t fit the open source stereotype. A much higher percentage than usual, for instance, are women.

Good good-first-issues don’t guarantee contributor retention. But we have also observed that when we consistently put out well-thought-through good-first-issues, contributors do come back.

Perhaps most importantly, thanks to Tern’s embrace of best practices for good-first-issues, we have a project that can handle increased interest and popularity organically. Because we’ve taken care to welcome people to the community and make it easy for them to increase their knowledge of the project, we now have experienced coders ready to help us grow when we need them.

One final thing: this work has impacted more than just our contributors.

Focusing on creating good-first-issues has required the project’s co-maintainers to create more easily-maintainable code. Our code is now more modular as a result, which puts us in better alignment with coding best practices.

It has also directed our focus as maintainers on perhaps the most important aspect of project maintainership: the project management, architectural, and design decision making that shapes it and helps it grow.

We’ve even found that good-first-issues can drive real change just by themselves. Not long ago we were able to complete a big feature in Tern almost entirely with good-first-issue-level contributions alone.