The purpose of this post is to outline how I got involved with Rust open source projects with a specific emphasis on the "softer" aspects of open source contributions such as finding them and interacting with project maintainers.
When I first got interested in open source, I struggled to come up with a way to find projects that welcomed contributions. Luckily, I discovered This Week in Rust which provides a list of projects that are requesting contributions to either specific issues or just to the project in general. So, I used the list provided in this newsletter in order to find contributions to make.
The first of these projects that I found was rusty-celery. The specific issue that they requested a contribution for was implementing origin information for message packets. To attach myself to an issue, I looked for issues on the rusty-celery repository marked with the tag "good first issue" and noted my interest. At first, I was confused by the code-base since it was all so alien to me. Then, I realized that in these instances, it is often best to just jump in, write a solution, and then validate it.
In this case, jumping in required me to review the source code for a Python implementation referenced in the issue. From that source, I deduced that the data I needed in order to implement the origin field would be the PID and the system host-name. For the PID, I used process::id from the Rust standard library. For the system host-name, I used the hostname crate.
After getting the relevant data, the next step was determining how to format it into a string. Initially, I tried using the + operator but this proved to be unidiomatic so I used the format! macro instead.
Once the process of determining the origin was decided, I wrote my solution to calculate the origin on each function call. This was inefficient as the maintainer pointed out as he said that the origin itself stays the same for a system regardless of how many times it is called; hence, it makes more sense to calculate the origin lazily such that it is only calculated on the creation of the first message packet and then it is saved to be referenced afterwards for new message packets. Determining the best route for this lazy evaluation involved a bit of trial and error but I found the documentation for once_cell immensely useful.
Regardless, one aspect of this experience of this experience that I did not expect is the number of iterations that would be required in order to produce code that could be merged in. I realize now that if one is to contribute to open source, then one should expect one's first solution to be imperfect and to be iterated upon. This expectation is key to making contributions to open source projects as one must recognize that one's contributions (especially at the beginning) will never meet the maintainer's standards at first. This is why it is necessary to be humble enough to accept the feedback of the maintainer in order to build a contribution that can be accepted.
The second of the contributions I made was to A/B Street, a project intended to make it easy to determine the effects of small changes to a city's transport infrastructure. I found this project by chance as I remembered that A/B Street had popped up on Hacker News a while back and since I have an interest in civic technology, I figured that contributing to this project would be right up my alley. Regardless, the approach I used to find an issue to work on was equivalent to the approach employed with rusty-celery as I just checked the issue tracker and found issues marked "Good First Issue".
That being said, as this project has a variety of issues marked with that tag, I decided between them by determining how much I would have to learn about the project to tackle each issue. So, I determined from the issue descriptions that parallelizing the importer would be the simplest issue to tackle as that involved a very specific part of the set-up infrastructure for the project and would only involve me using elements of the Rust standard library rather than learning anything about the computer graphics, and UI systems used in the project. This isn't to say that one should not attempt to familiarize themselves with those things but more that I found doing so to be intimidating so I figured it would be best to do something simple for now.
With regard to the implementation in this instance, I found my knowledge regarding the context of the project lacking enough that it was difficult for me to ascertain the correct approach early on. So, I figured my best move was to look at the existing code, write comments outlining how I would go about parallelizing it and then make a comment enabling the maintainer to scrutinize my proposal. This allowed me to validate my approach before putting the effort in to code it up.
Luckily, there were no issues with my proposal and implementing it was fairly easy as it was more or less a copy-paste of the Rust book's threads example. After a few more iterations, it was accepted and merged into the code-base.
Another project that was requesting contributions on This Week in Rust was the Boa project. Boa is a project which seeks to build an embeddable Javascript interpreter in Rust. For this project, I found an issue related to eliminating some redundant code with regard to Boa's implementation of the typeof function in Javascript. As with A/B Street, I found this by looking for issues tagged "Good First Issue".
After implementing this relatively straightforward issue, I encountered a baffling failure on Boa's CI pipeline. Unfortunately, I struggled to reproduce this failure locally; hence, I made a comment on my PR asking one of the maintainers to take a look for me. Which brings me to one of the many things I learned in my experiences in open-source so far, which is that if you ever need help you should just ask rather than simply spinning your wheels aimlessly. It's better to make progress with someone else than to make none at all on your own.
It turned out later that the failure I encountered was a result of code introduced elsewhere by another PR which made me realize that in the future, any CI failures I can't reproduce locally are likely caused by my version being out of sync with the current master. Nevertheless, after that, I iterated on my PR further and it got merged in later.
From these experiences, I have learned the following: