First experience with an open source project

LIU ZISHAN/SHUTTERSTOCK.COM

Overview

In this post I would like to share my experience working on an open source project, focusing on fundamental aspects and describing the process of contributing to an open source project step by step.

Open source is a piece of software the source code of which is available for use and/or modification.

The majority of open source projects live on github, which is based on git (version-control system). Thus, knowledge (at least some) of git is fundamental, not mentioning that it is one of the tools every developer should know how to use.

Filer

The project I have been working on is called Filer.

Filer is a POSIX-like file system interface for node.js and browser-based JavaScript.

It allows you to do things that you do on your computer (create, read and write files, create/delete/rename folders, etc.) but in a browser! Filer supports the majority of modern browsers, the full list can be found here.
Filer a nice page called CONTRIBUTING, that provides detailed instructions on how to become a part of the project.

Set up 💻

In order to work on any project on GitHub you need to have a GitHub account. The accounts are free, with premium features, like private repositories available for subscribers.

For development (especially web) I prefer to use MS Visual Studio Code (it is absolutely free!) since it has a very nice interface, git integration, integrated command line and hundreds of other features and extensions.

Here are the steps I did to get the copy of the project and prepare the environment for development of new features.

  1. Create a fork of the repository on GitHub. Navigate to the project you are working on and click ‘Fork’ button.

2. Clone a forked repo to my computer.

To get a local copy of the project open integrated terminal in VS Code (click ctrl + ` on Mac), navigate to the directory you want to have your code in (‘cd dirName/’) and use git clone command with your forked repo url.

git clone https://github.com/YOUR_PROFILE_NAME/filer.git

To find url, go to you profile page, click repositories, find a repo you forked, click green button ‘Clone or download’ and copy the url.

(If need help use GitHub documentation)

Find an issue 🔬

To make a contribution to a project you need to know what change you want to make to it. It can be a new feature, a bug fix, a change that would increase performance, etc.

I started by looking at existing methods and unit tests for them. Filer provides methods similar to methods from Node.js FileSystem module.

After checking the code I found that Filer does not have tests for mkdtemp method, which is used for creating temporary directories. This method can accept a custom prefix from the user and will append a unique character set. It allows to create temporary folders without having errors (in particular it will always create a directory with a unique name avoiding having an error that folder already exists). I created an issue where I described what I found, and suggested to write test methods that were missing.

Later, I discovered that Filer does not have mkdtemp method at all! So, it was obvious that I would not be able to fix my first issue, without fixing this problem. I created a second issue, suggesting to implement mkdtemp method that would be similar to Node.js fs.mkdtemp method.

Github stores issues and assigns unique IDs we can use to find and reference them later. Additionally, when we will create a pull request that fixes the issue (which is basically a submission of our work for an approval and merging), the issue page will have a link to that pull request!

Fix/resolve the issue 🔧

Now, when I found what changes I want to make to the project and created issues on github, I can start coding 🤓.

First of all, I created a new branch from a master branched of my forked repo and checked out.

You can do it with command:

git checkout -b issue-441

where 441 is the number of the issue I created on GitHub.

The same action can also be done in 2 steps:

git branch issue-441
git checkout issue-441

I found that all Filler’s methods are defined in a file called “implementation.js”, while list of available methods (prototypes) is defined in “interface.js”.

I had an idea that I could use some logic of mkdir method, since mkdtemp also creates a directory. To generate a unique character set I modified a shared method guid() to generate a set of 6 characters instead of 36. The final function looks like this:

function mkdtemp(fs, context, prefix, options, callback) {
     callback = arguments[arguments.length - 1];
    // this function is used to generate a random character set to append to tmp dir name to make sure it is unique
    function generateRandom() {
       return 'xxxxxx'.replace(/[xy]/g, function(c) {
       var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
       return v.toString(16); });
     }
  if (prefix) { 
   var path = '/'+prefix+generateRandom();
   make_directory(context, path, function(error) {
   if (error) {
     callback(error, path);
   } else {
      callback(null, path);
 }
  });
 } else {
   callback(new Error('filename prefix is required'), prefix);
 }
}

Randomly generated character set gets appended to a prefix and the path gets passed to make_directory function.

mkdtemp method returns an error and a path to created temp directory.

In addition, I wrote unit tests to make sure that this new method was working the way node’s mkdtemp method works. I created a new branch for it, to make a separate pull request.

Test your code 🗜

It is crucial to test your code before you commit any changes. Debugging and finding errors can take a lot of time, because you need to make sure that you don’t break something when you add new features. To make sure that code works properly we can run unit tests. They will be executed and the report will show errors if anything is broken.

Filer uses mochajs and the chai expect assertion library for its tests. Test files can be found in tests/spec directory.

Using next command we can run tests directly in browser, which has a clean and easy to read user interface, and also allows us to select specific tests we want to run with just 1 click.

npm run test:manual

Additionally, using npm test command we can validate our code, even for missing semicolons! (My first couple commits were missing semicolons, because I only ran in-browser tests which did not show those errors)

Commit, push, pull request 🚀

The next step — commit changes to git. It can be done in multiple steps.

git add implementation.js
git add interface.js
git commit -m “your message”
git push origin

After this steps, the forked repo now has a branch that was created earlier with the changes that were made.

Now, after this step, on the page of the fork I created on GitHub the branch I pushed become visible, and GitHubb suggests to create a new Pull Request.

I created a new PR describing changes I’ve made and included the number of issue I worked on. (The issue page now also has a link to this pull request!)

Later I created a second pull request that added unit tests for mkdtemp method.

Review pull request 👀

Developers can review pull requests other people created. It helps to catch errors before merging changes, suggest something for improvement or just let them know that they did a good job.

I looked at this pull request and navigated to the issue that was associated with it. I read the description of the issue and then compared it to changes that were made in the pull request. The issue created suggested adding a test for a “rename” method that would check for renaming a directory that does not exists. It was a very good idea to add this test, since the function is supposed to throw an error if the user tries to change the name of something that does not exist.

I also found that the user added a lot of white spaces in the existing code, which now shows as a change made in last commit. I saw the exact same thing in other pull requests, and it seem to be related to code formatting made in the editor.

Address other’s reviews ✏️

Other people can also add comments about my pull request. My pull request have received a couple of comments regarding implementation of the code and typos in comments. GitHub allows to add comments to specific line which helps to quickly navigate and see where the problem other users mentioned is, so we can fix it faster.

The major discussion on my pull request was about passing encoding parameter to mkdtemp function, and using it to create a temporary directory. At the moment I implemented this method, I allowed the user to pass options argument, however Filer’s method for creating directory does not use this parameter, so it remains unused inside my method as well.

Communicate with others 📢

It is important to ask other people questions and answer their questions. There are many ways to communicate — on GitHub itself, using services like Slack or in person. Slack is useful because many people may have same questions, and there is a chance they may find answers in previous messages.

In addition, you have a list of people who work on the same project and you can ask them question. Since everyone in my class worked on this project I discussed the project with people I knew during our class or messaged them on Slack. So don’t be afraid to ask people, especially if they have more expertise and can give good advices!

Conclusion

This was my first Open Source project experience and in just 2 weeks I have learned a lot of new things about open source, working on big projects with big number of people online, enhanced knowledge of git and learned GitHub features I did not know about.

It has been interesting an exciting to work on this project and I am looking forward to contribute to more projects.