Introduction

This book serves as a guide to Open Source contributions. It is a work in progress, and is intended to be a living document. It is not intended to be a comprehensive guide to all things Open Source, but rather a guide to getting started with Open Source contributions.

This details my own personal workflows, and describes the tools I use on a day-to-day.

Me

I am a software developer at freeCodeCamp. I develop course and curricula content for freeCodeCamp, and I also develop the software used to deliver the content.

I develop on the whole stack - front-end and back-end. I also develop on the heap - the database. I have developed a variety of courses, such as:

Set Up

The tooling I use on my day-to-day.

Operating System

Windows 11

Yes, I use Windows for software development as my primary workstation 🙄.

I have been using Windows since XP, and have become very comfortable with it. I tried my hand at Ubuntu, Lubuntu, Mint, Raspberry PiOS, and MacOS, but I always come back to Windows as my primary workstation.

File System

Ubuntu 22.04

What? I thought you said you use Windows? 🤔

Oh, right 😅. Did I forget to mention... I use WSL 2 on Windows 11 for my day-to-day development.

Windows Subsystem for Linux (WSL) is a compatibility layer for running Linux binary executables (in ELF format) natively on Windows 10+ and Windows Server 2019+. WSL provides a Linux-compatible kernel interface developed by Microsoft, which can then run Linux distributions in user mode on Windows 1.

Terminal

Windows Terminal 2

Powershell is useful and all, but it is difficult to use most developer tools with it; the software world has just leant towards using UNIX-like shells. I have found connecting to WSL though Windows Terminal to be convenient, as Windows Terminal allows multiple terminal sessions in tabs.

split terminals

Oh My Bash Oh-My-Bash 3

I use Oh-My-Bash, which is a bash shell with a bunch of useful plugins and themes. Here is my current config: https://gist.github.com/ShaunSHamilton/afe0f6c79fa10fcb5ea83436f98fa5b0

The only custom bits are:

  • The timestamp shown in the prompt
  • The terminal tab title is set based on the directory I am in
  • The prompt includes my silly emojis letting me know what kind of project I am working on

my terminal

Tools

Node.js

Fortunately/Unfortunately, I have the luxury of being able to use Node.js for a lot of my work.

I install Node.js using Node Version Manager (nvm) 4:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash

Once installed, I can install any versions of Node.js I want (except for v999):

nvm install 1
nvm use 1

Do not actually install Node.js version 1. It is just an example.

Rust

one does not simply rewrite it in rust

...but I usually do.

Rust is more than just a programming language or a compiler. It is a community of developers who are passionate about building fast, reliable, and efficient software.

Rust makes things go BRRRR!

rustup

With that community comes an ecosystem of tools. The brilliant thing about this ecosystem is that it is not the hodge-podge of tools that you find in the JavaScript ecosystem. The tools are all designed to work together, and they all work well together. Part of this is because the main tooling is developed by the same people who develop the language itself.

Which brings us to rustup - the Rust toolchain installer:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Rustup handles installing rustc and cargo. rustc is the Rust compiler, and cargo is the Rust package manager.

rustup is to rustc is to cargo as nvm is to node is to npm.

Docker Desktop

one does not simply dockerize it

Docker Desktop is a tool for developers and sysadmins to develop, deploy, and run applications with containers. I use it to deplete my drive space with containers.

MongoDB

friends don't let real friends use relational databases

I guess if you program in JavaScript, you have to use MongoDB. I don't know why, but it is what it is. 🤷‍♂️

Setting up MongoDB on WSL can be a pain. In general, be sure to follow the Install MongoDB on Ubuntu docs.

If you decide to use a different Linux distro, be sure to follow the docs for that distro.

After following those docs, you might be able to start MongoDB with:

mongod

More likely, you will get an error like:

{
  "t": {
    "$date": "2023-04-16T20:27:21.912+01:00"
  },
  "s":"E",
  "c":"CONTROL",
  "id":20557,
  "ctx":"initandlisten",
  "msg":"DBException in initAndListen, terminating",
  "attr": {
    "error": "NonExistentPath: Data directory /data/db not found. Create the missing directory or specify another path using (1) the --dbpath command line option, or (2) by adding the 'storage.dbPath' option in the configuration file."
  }
}

In which case, you would search this on the search engine of your choice: Let Me Google That For You.

You might see an answer like:

sudo mkdir -p /data/db

Trying again, you would see this error:

{
  "t": {
    "$date": "2023-04-16T20:32:24.033+01:00"
  },
  "s": "E",
  "c":"CONTROL",
  "id":20557,
  "ctx":"initandlisten",
  "msg":"DBException in initAndListen,
  terminating",
  "attr": {
    "error": "IllegalOperation: Attempted to create a lock file on a read-only directory: /data/db"
  }
}

In which case, you would do even more searching:

all programmers are google engineers

Stumble upon something like:

sudo chown $USER /data/db

Now, you should be able to start MongoDB:

mongod

Git Started

git good

I am not an expert at Git. Just ask my friends 🙄 I do get by, though.

Contribute

Forking

fork freecodecamp

Cloning

git clone --depth=1 https://github.com/<USERNAME>/freeCodeCamp.git

git clone --depth=1 https://github.com/ShaunSHamilton/freeCodeCamp.git

Upstreaming

To keep your fork up to date with the upstream repository, you need to add the upstream remote.

git remote add upstream https://github.com/freeCodeCamp/freeCodeCamp.git

Look what you did:

git remote -v

Often, it is recommended to use ssh instead of https. Something to keep in mind 🤷‍♂️

Exploring

On freeCodeCamp, issues start off their life as status: waiting triage. This means a maintainer of the repository has not reviewed the issue to a point of concluding what it would take to close it.

Sometimes, issues require more discussion (status: discussing) before they can be triaged. This usually happens when it is not clear whether the point raised is something immediately actionable/desirable for the project.

Once an issue is triaged, it is often opened up to the community to contribute to. These issues are labelled help wanted or first timers only. Issues labelled help wanted are open to all, but usually require a bit more knowledge of the codebase than first timers only issues, and the maintainer comments on the related issue are not always as explicit about what needs to be done.

Find yourself an issue to contribute to: Issues labelled help wanted

Updating

Ensure you have the latest changes from the upstream repository:

# Ensure you are on the default/working branch
git checkout main
# Fetch the latest changes from the upstream repository
git fetch upstream
# Reset your local branch to the upstream branch
git reset --hard upstream/main

Branching

Create a new branch for your contribution:

git checkout -b <BRANCH_NAME>

git checkout -b fix_too-much-sound

The format I use for my branch names is: <TYPE>_<DESCRIPTION>

Where <TYPE> is one of: fix, feat, docs, chore, refactor, revert
And <DESCRIPTION> is a kebab-case, easy to remember, description of the change

You may notice others using a forward slash instead of an underscore. This is fine, but confuses me when performing git ops like:

git checkout remote/origin/fix/some-bug

Too many slashes 😱

Committing

So, you have just made your awesome changes:

- console.log('Hello, World!');
+ console.log('Hello, 🌍!');
# Add all changes to staging
git add .
git commit -m "<COMMIT_MESSAGE>"

git commit -m "fix(client): prevent sound on every render"

Pushing

Push your changes to your fork, creating a new branch on your fork to follow:

git push -u origin <BRANCH_NAME>

git push -u origin fix_too-much-sound

Now, you can open a pull request from your fork to the upstream repository.

Changing

A maintainer of the upstream repository may request changes to your contribution. You can make these changes on your local branch, and push them to your fork.

- console.log('Hello, 🌍!');
+ console.log('👋, 🌍!');
git add .
git commit -m "<COMMIT_MESSAGE>"
git push

Maybe you want to give credit to whoever suggested the change. You can do that by adding a Co-authored-by line to your commit message:

git commit -m "<SINGLE_LINE_MESSAGE>


Co-authored-by: <NAME> <<EMAIL>>"

git commit -m "emotify entire log message


Co-authored-by: Shaun Hamilton <51722130+ShaunSHamilton@users.noreply.github.com>"

Pay attention to the two empty spaces between the commit message and the Co-authored-by line. This is important.

Side Step

The beauty of the open-source community is evident in its "I see, therefore I fix" attitude. This is often the best way to get started, and to keep going; whilst developing your own projects, you will inevitably come across bugs in the tools you use. Why not fix them?

The Bug

Let's say you are working on a project, and you come across a bug 🐛 in a tool you use. You can either:

  1. Ad-hoc fix the bug in just your own code
  2. Use a different tool
  3. Fork the tool, fix the bug, and use your fork
  4. Contribute to the tool

Pick option 4.

At the very least, it is worth checking the tool's issue tracker to see if the bug has already been reported. If it has, you can add a comment to the issue, or even better, you can submit a pull request to fix the bug.

Example Time

You are writing a certain book-like thing using mdBook bootstrapped with mdbook-admonish.

Writing an admonish block has the following options:

```admonish note
Default with title="Note"
```
```admonish note title="Another Title"
Default with title="Another Title"
```
```admonish note title=""
No title is shown, and the cute little icon is not shown
```

🤔But you want no title, and you want the cute little icon to be shown. How do you do that?

A little bit of hacking, and you discover title=" " does not work, but title="&#x200b;" does. That is odd. A 🐛??

The Report

After searching the issue tracker, you find that the bug has not been reported. So, you open an issue.

The issue contains as much information as is relevant, and is polite and respectful. Including a code example or two goes a long way.

The Fix

A maintainer of the project gets back with some actionable steps to close the issue. You decide to fix the bug, and submit a pull request.

First, you should probably read any contributing guidelines the project has. Usually, these are located in a CONTRIBUTING.md file in the root of the repository, or mentioned in the README.md.

Then, you go through the whole Git Started process again.

gru recursion

Overview

Contributing a fix to the software you use may not always be possible due to the scope of the bug, or the aliveness of the project. However, it is worth trying, and is an excellent way to develop your developer skills.