Fixing issues in OSS is easier than you think
Tags: opensource, ruby
Published: 2020-11-12 07:17:28

Issue fixing is the most common way to contribute to open source projects. And I believe many of you want to contribute to OSS projects in this way. But the idea of solving an issue on your own can also be intimidating. For example, when you open up an issue report and try to work on it, you may find it difficult to start because

* You don't have sufficient information about the bug
* You don't know how to reproduce it
* You are not sure if that's really a bug of the project or just an unsupported use case

I don't know if the above scenarios have happened to you before, but I surely experienced it a lot in my earlier days as a contributor. At that time, it prevented me from committing to an issue because I was afraid that I couldn't finish on my own.

But who said that we need to fix an issue alone? Although solving an issue on your own is surely a great thing. However, it's also often to see people solving issues collaboratively. So in this post, I want to show you how to break down an issue and make your contribution in different ways.

## So you want to fix an issue?

Regardless of the issue's subject, here are the first few things you should do in most of the projects:

1. Clone the project
2. Follow the contributing guideline to set up the project (install dependencies, required services...etc.)
3. Run the test suite and make sure they pass locally. If some of them failed, it could mean:
  - You haven't completed the setup or didn't do it correctly
  - There's a compatibility issue between your environment and the project, which could be another contributing opportunity

Then depending on the issue, you might be able to start working on it right away. But it's also possible that you meet some obstacles and don't know how to proceed, as I mentioned earlier:

* You don't have sufficient information about the issue
* You don't know how to reproduce it
* You are not sure if that's really a bug of the project or just an unsupported use case


Those obstacles, however, are actually the thing you can and should contribute to. Just answering any of the questions will make the issue one step further to be solved, either by you or others. 

## But what if I don't get any credits from it

I know most people contribute to open source projects with the hope of helping their career growth with some nice showcases to put on the CV. I'm no exception. So I understand that spending dozens of hours to help others landing a bug fix PR doesn't feel like a good investment.

But here's how I look at this: Many companies still use whiteboard interviews or homework assignments to test their candidates' problem-solving skills. However, since most of the companies aren't so great or have enough resources at hiring, those processes designed by them don't necessarily demonstrate your real capability.

So why not using the issues you helped solving as evidence? Any issue you help solving can be a great proof of your conversation and coordination skills, whether it's a reproductions script you wrote or a comment to express your opinion on the solution. Sometimes, those non-coding contributions are as valuable as your PRs. Like this [comment](https://github.com/getsentry/sentry-ruby/issues/738#issuecomment-592720365)

If you agree with my point above, let me show you how to contribute to an issue under different scenarios.


### Not having sufficient information about the issue

Sometimes, the issue description may not provide sufficient information about the issue itself or the requirements to reproduce it. And if the project maintainer(s) don't have time to go after them one by one, the issue could remain unhandled for a while.

Usually, a ready-to-solve issue should contain the following information:

* The user's environment when encountering the issue, including
	1. Project version (e.g., sentry-raven 3.1)
	2. Language version (e.g., Ruby 2.6)
	3. Operating system (e.g., MacOS 10.15.6)
	4. The version of other important libraries (e.g., Rails 6.0)
* The expected behavior
* The actual behavior
* Reproduction steps

So if you found any issue that lacks the above information, you can kindly ask the issue author to provide more info to let you start working on it. For example:

* Hello @st0012, I'm interested in investigating this issue further, but I need more information to do so. Can you also tell me what Ruby version did you use when seeing the error? Thanks 😄

Usually, the author will reply rather quickly to move the issue forward. And once he/she has provided more information, you or other people can start working on it.

### Not sure how to reproduce the issue

If an issue can't be reproduced, it can't be solved with confidence. So if you find the reproduction steps are missing from the issue, you can be the one that provides one by

* Creating a minimal app that can reproduce the issue with the given (or fewer) reproduction steps so other people can have an actual app to see the bug happens.
* Or writing a reproduction script that can demonstrate the problem just by executing it. A great example of this is [Rails' bug report templates](https://github.com/rails/rails/tree/master/guides/bug_report_templates).
* Best scenario: writing a new test case for it
	* If you're certain the cause of the issue locates inside the project, this will be the most helpful thing to do.
	* This could be hard because you'll also need to set up the project locally and make it runnable. But if you managed to do it, to you, the issue is more than halfway through!

Even if the author already provided reproduction steps, you can still try to reproduce the issue with a different setup, such as using a newer version of a library or Ruby to see if it still happens. This can help you and others find out the potential cause of the issue.

### Validate the issue's cause

Even if the issue can be constantly reproduced, it doesn't necessarily mean it needs to be "fixed" for reasons like:

* Not the expected usage of the project
* Caused by something else:
	* a conflict with other projects
	* a bug in the dependencies

So you need to validate the issue by understanding the project's scope, its dependencies, and the user's use case. Sometimes this also requires having a discussion with the project maintainer and other users of the project.

You might feel like doing broad research in the step. But if you do it thoroughly, this will be the step you'll learn the most from. Here're the things you can do:

* Dive into the codebase and locate the root cause and report what you've found in the comments
* If the issue is caused by the project's bug, find the commit/PR that introduced it and share it in the comments. This will help tremendously. If it's a complicated issue, I also suggest you write down the paths you've visited during the investigation.
* If you're already familiar with the project (e.g., you're a heavy user), provides your opinion about the issue. This will help the maintainer decide whether to fix it or not or how to fix it.

### Fix It!

If the issue you're looking at already has a detailed description, a reproduction script, and has been verified as the bug of the project, why not be the one that fixes the issue? Especially when you're the one that completed the previous steps, you can now call yourself the expert on the issue should be the best candidate to fix it!

This part is pretty straightforward, as most of us fix bugs for a living 🙂. But I still want to provide some tips for you:

1. Since it's a bug fix, you should add test case(s) that will fail without the fix (unless there's a reason not to so). I suggest you write the test cases before making any code changes. TDD works pretty well when fixing bugs for open source projects.
2. Don't mix refactoring with bug fixes in the same commit. I know some refactorings might be inevitable for fixing the issue properly. So make sure you give the refactoring a standalone commit, which makes the code review a lot easier.
3. Be patient. Every maintainer will be grateful to see you help them fix a bug and will try to merge the fix as soon as possible. But most of the maintainers maintain the project in their free time (which is very limited), and they could be busy reviewing other PRs or fixing other issues. So you may not get a quick response to the PR you just opened. I know how frustrating it could be, but it doesn't mean they don't cherish the hard work you just made.
4. Make sure the maintainers can review your PR as easily as possible. This can be done by:
	1. Making sure your PR pass the CI
	2. Making sure your code follows the coding style guide of the project
	3. Explaining the cause of the issue in detail. Like:
		* because `method_a` called `method_b` at `file.rb:120` with the string `"foo"` under certain circumstances, it caused the `baz` method in `Bar` class to return the incorrect `"xyz"` result and caused this issue.
	4. Depending on the nature of that issue, there could be multiple ways to fix it. So you may want to explain the approach you chose and why you think it's the best approach
		* since the `method_b` is a private method that is only called by `method_a`, I figure adding an argument check in `method_a` will be sufficient to prevent this from happening again.

The key concept is: make your PR's purpose clear, so even a busy maintainer can easily review the content.

## Final Note

I'm not sure if you have noticed them, but the steps above actually make a full process of solving an issue. Each one of them helps understanding the project better from a different aspect. This means that even if you only make a partial contribution at a time, sooner or later, you'll be capable of solving an issue by yourself.

So I hope after reading this post, you're now more confident about making your first or next contribution to open source projects. It's really not that hard to do. And as a community, we really need your contribution to keep the projects moving forward!