Open Source Curation
There’s a lot of open-source software out there, and we often need to use multiple libraries to accomplish our goals. But sometimes, libraries and tools don’t work together cohesively. There’s a lot of value in filling in the gaps.
A Story
I’ll start with a story about a recent set of open source contributions I made. If the story gets too long or involved, skip down to the Lessons Learned section at the end.
Background
I’m the primary maintainer of a package we created at work, eslint-config-zeal. We use this package as a common configuration for ESLint on our projects. We include a configuration for every single rule provided by ESLint and several of its plugins. Some rules we disable, some we customize, but all rules are listed.
In order to maintain eslint-config-zeal, we need to keep it up to date with changes in ESLint and its plugins. Making sure that we’ve configured every rule is tedious and error-prone.
Along the way, I ran across a handy little utility called eslint-find-rules. Among other things, it can examine an ESLint configuration and report a list of “unused” rules - rules that are available, but not listed in the configuration. This utility is a life-saver for a project like eslint-config-zeal.
However, it had an issue. From time to time, some lint rules are deprecated in favor of replacements. If we include configuration for a deprecated rule, ESLint prints a deprecation warning, so we’ve made a habit of removing these rules from our configuration. But eslint-find-rules reports those rules as unused, resulting in it exiting with an error (or at least reporting spurious failures when run with its --no-error
flag). I found that Michał Gołębiowski had already opened an issue for this limitation.
I decided that I’d like to fix the problem, making the tool better for everyone. It seemed like it should be relatively easy to fix, so I started digging into it.
Problems
I immediately ran into a few challenges:
-
ESLint didn’t have any kind of public API for determining if a rule is deprecated. The rule metadata contained a
deprecated
flag, but there was no documented way of getting at the metadata. In fact, eslint-find-rules was essentially enumerating the files in ESLint’srules
directory to determine what rules are available. -
Some of the plugins we use also had deprecated rules, but most of them only mentioned that in their documentation. eslint-plugin-react included some information about deprecated rules in its metadata, but it was done differently than ESLint itself. Fortunately, plugins do have a documented way of accessing the rule definitions, because that’s how ESLint interacts with the plugins.
Solutions
-
By the time I was able to start working on this, Michał had opened an issue on ESLint asking for an API to access rule definitions and learned that there was already a proposal for such an API. Ilya Volodin implemented the proposal, and the
getRules
API was released in ESLint 3.12.0. -
While waiting for this work to land, I went ahead and did some preparatory work so that everything would be in place once I was able to implement my changes.
-
I opened a pull request on eslint-plugin-react to add a
deprecated
flag to the metadata of deprecated rules in a way that was consistent with the base ESLint rules. This change was merged and released in v6.5.0. -
I opened a similar pull request on eslint-plugin-import. This change was merged and released in v2.1.0, though not mentioned in the release notes.
-
I opened a documentation PR on ESLint to document the
deprecated
flag so that plugin authors would be aware of its existence and use it in their rule definitions. This was merged and released in v3.8.1.
-
-
Once the
getRules
work landed in ESLint, Michał opened a new issue on eslint-find-rules to make use of this API. This work would prepare for being able to skip deprecated rules when reporting on unused rules. -
I started working on using
getRules
. I had to update the ESLint dependency to v3.12.0 to get access to that API, and found that this introduced a large number of dependency conflicts that would not be easy to resolve. Fortunately, I found that Sarbbottam Bandyopadhyay was already working on this as part of a more general ES-Next upgrade. After waiting a while, the PR seemed stalled, so I offered to help get it moving. I turns out that I didn’t need to do anything, and the upgrade was completed within a few days. -
I was finally able to switch over to the getRules API. That PR was merged and released in v2.0.0.
-
With
getRules
in place, I was finally able to make it omit deprecated rules. This change was merged and released in v3.0.0.
As you can tell, this was a long and somewhat tedious process involving contributions from a number of people. I first started looking into this on October 7, 2016 and v3.0.0 of eslint-find-rules was released on June 14, 2017. There were a number of gaps in here, waiting for things to happen.
Lessons Learned
Most pull requests to open source projects are relatively simple: tweak something here, fix a small bug there, clean up some documentation another place.
Others are more involved, adding significant new features, but still contained within the boundary of a single project.
Some of the most valuable contributions to be made are found in the gaps between projects.
Often it’s not clear which project needs to change to support better integration; sometimes it’s both.
But who is going to take responsibility for the overall work?
Most open-source maintainers are already overwhelmed with the “normal” maintenance of their projects. Having to worry about the middle ground issues just adds to the burden.
If you’re looking for a place to contribute to open source, start looking in the gaps between projects. Are there some libraries you use that don’t quite work together the way they should? Have you written some “glue” code in your application to get around this? Do you have extra code to work around inconsistencies?
What can you do to contribute this back so that other people can benefit?
Maybe you could write a blog post about it.
Maybe you could release a small library that contains your glue code.
Maybe you could contribute some code to both projects to make them work together better.
Maybe there’s already some work in progress and you could offer to help to move things along.
Maybe the projects can work together without changes, but you could add or improve the documentation to make it clearer to others.
Maybe you’re more skilled at organizing work and managing projects than you are at coding. You could use those skills to coordinate the work of others and make sure that all of the pieces of the solution fall into place.
As you can see from my story, I did a little bit of all of these things. I contributed code and documentation to several projects, but I also asked questions and relied on the work of others to get to the final destination. I offered to help where I could.
This kind of integration work can be more challenging than contributing to an individual project. It can also take longer to get all of the pieces to fall into place. But this is also some of the most valuable and rewarding open-source work you can do.
Other Examples
There are certainly other people in the community who do this kind of work. Dan Abramov and team have done a great job with this on create-react-app. create-react-app is a project that brings together a number of other tools and libraries into a cohesive whole that works well. Often, this involves finding and fixing issues in upstream projects so that the whole collection works well.
Projects like browserslist take common infrastructure needed by several other projects and pull it into a new library that everyone else can use.