Effective Open Source
I’ve been using open source solutions for years, but I was mainly sitting on the consumer side of the table rather than giving back to the community as a contributor. In the last couple of months I was lucky to finally have enough time be effective as a contributor. During this period I sent pull requests to some smaller libraries and to the Node.js core as well, but I spent most of my time with optimizing the performance of a Node.js web framework called restify. As part of this journey, I took some side roads when I felt frustrated by the overall experience of contributing to a project. Both as a contributor and as a maintainer, I wanted to eliminate all the subjective factors and manual steps possible, from the process.
These involved replacing manually-written API documentation with a JSDoc-based, generated one, making the linter stricter, and introducing some helpful automation to make maintaining the project more efficient. This article summarizes what I have learned during these months and what I find useful as a first-time contributor, or, as maintainer.
Strict Linter Rules
One of very my first frustrations was that I faced as a contributor came from the fact that almost every project have different code structure and style and many of those rules are not clearly written. These rules only exist in the mind of core contributors. It’s quite hard for a first-time contributor to know what the unwritten expectations are, regarding safe code and good style. There are some great projects supporting a common code style, like standard, or the AirBnB JavaScript Style Guide which comes with linter configuration as well. Although based on my experience, these base rules need to be extended because they do not cover all the expectations of the core maintainers, they are not strict enough.
For example in restify, we avoid using anonymous functions as it’s hard to debug a JavaScript code where functions don’t have names. This is our personal preference, most of the people don’t do this. One of the best ways to let a first-time contributor know is adding a linter rule.
Adapting Code Style
In the previous sections, I emphasized the stricter ruling to provide an unopinionated way for both the contributors and maintainers to deal with code changes. But isn’t it overwhelming to follow so many strict rules per different projects? I think it is, but let me tell you there is a solution.
Code formatters, like prettier are capable of taking your code and reprint it from scratch in the expected code style. See, you don’t even have to adapt your coding style. Write your code as you would do in other projects and let it auto-format before committing.
Generate Your Documentation
During my contributions, it’s turned out that is hard to keep the documentation in sync with the code base itself. Especially the small details, like the type of the function parameters and the return value, but I also found some minor mistakes regarding method visibility and public names. As a result of this, we decided with restify to address the issue by replacing the manual documentation with an automatically generated JSDoc based solution. We are using the eslint-plugin-jsdoc package to ensure that the JSDoc comments are in sync with the code base, and everything is documented correctly. We use the documentation.js library to generate the human readable markdown files from JSDoc comments for our Jekyll based API docs site.
Example markdown output:
### address
Returns the server address.
Wraps node's
[address()](http://nodejs.org/docs/latest/api/net.html#net_server_address).
**Examples**
```javascript
server.address()
```
_Output:_
```javascript
{ address: '::', family: 'IPv6', port: 8080 }
```
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Address of server
Code Coverage
In lots of cases, the expectations of the maintainers regarding code coverage doesn’t match with what contributors want to see in their projects. Improving test coverage is one of the most common things what maintainers ask from contributors during code review. To help contributors maintain, or increase code coverage of your preference, you should integrate a code quality and coverage tool like Coveralls to enforce your expectations. It reduces the iterations between you and the person opening a pull request, because they will know up-front, what your first comment as a reviewer would’ve been.
Don’t forget, the contributor might have had enough time during a weekend to send a PR, but they might not have time during the upcoming weeks to address your change requests. You should always be looking out for possibilities to minimize the uncovered areas.
Commit Convention
Following a guideline and using meaningful description when you are making a commit message not just helps the person who reviews your code but can also be used for generating CHANGELOG.md automatically, hence speeding up the release process. Check out the Conventional Commits project for the specification and available tools.
Commit message template:
<type>[optional scope]: <description>
[optional body]
[optional footer]
Example commit message:
feat(parser): adds ability to parse arrays.
BREAKING CHANGE: parsing options now take precedence over config files.
Automate Releasing
Most of the maintainers spend more time reviewing and releasing others’ code changes than writing actual code into the project. To minimize the effort what it takes and to avoid burnout, you should automate everything that’s possible in your project. In the previous sections I mentioned some ways how to introduce code-style, test coverage and documentation guidelines, now let’s see how you can speed up your release flow.
Following the conventional commit message format, it’s possible to generate the CHANGELOG.md file automatically, and determine the next SemVer compatible release version from the commits. You can integrate the semantic-release library to your project and publish to npm automatically for every commit that went to the master branch with the changelog together.
For those who want to have more control over release, and versioning, there is an excellent library called unleash, that can save plenty of time by automating the changelog generation, bumping versions in the package.json file, publishing to npm, and tagging in git.
Example usage:
unleash --minor
Useful Scripts
To maximize your productivity as a maintainer, you can write many useful scripts to increase efficiency, like generating documentation, fixing coding style issues, checking dependencies for known security vulnerabilities, or automating the release process. You can include these scripts in your package.json file, or you can create a Makefile for longer scripts.
You can either run your scripts manually, or you can use git hooks to run them before, and after committing or pushing a change. You can even run them on your CI for every commit or as part of your release flow.
Example Markdown file:
NODE := node
NSP := ./node_modules/.bin/nsp
DOCS_BUILD := ./tools/docsBuild.js
BENCHMARK := ./benchmark/index.js.PHONY: nsp
nsp: node_modules $(NSP)
@($(NSP) check).PHONY: docs-build
docs-build:
@($(NODE) $(DOCS_BUILD)).PHONY: benchmark
benchmark:
@($(NODE) $(BENCHMARK))
Issue Templates
It’s possible to create templates for issues and a pull requests on GitHub. Contributors will see template’s content when they open a new issue, so they can have an idea about what information is expected when filing a bug, asking for a new feature, or help. Templates are also helpful to keep the project’s issues organized as they usually provide a structure for contributors. As both a first-time contributor, or as a maintainer, I always find templates extremely useful.
For example here are some things that we ask from restify contributors when they plan to file a bug report: (you can find the full issue template here).
- Restify Version
- Node.js Version
- Expected behaviour
- Actual behaviour
- Repro case
- Cause
- Are you willing and able to fix this?
Be Nice
I left the most important thing for the end. Most of the people do open source in their free time without any compensation. Don’t expect the same kind of support and availability what you would have when developing commercial software. Always be patient and grateful when someone is willing to help you with either giving a helping hand, contributing to your project or reviewing your changes. Try to give that person any help and information to make their “work” more comfortable.
Some kind words can feel good and motivate people.
Outro
Contributing to an open source project or maintaining one, can be frustrating sometimes, given the special nature of these projects. But you can do so many things to make it effective, and a great experience for both parties. Remember, most of the people do open source it in their free. Let them enjoy it!
Don’t forget, most of these practices can be also applied for your private projects. Did I miss something, or have a suggestion? Let me know what practices you like apply, to keep your project maintainable. Share your thoughts in the comment section!