The activity charts of GitHub are a well known feature; some love them, some hate them. These charts are displayed on the profile page of users on the site, and represent a users contribution activity across the site in yearly blocks. This post is going to cover working with tools that can extend your GitHub activity charts to represent your overall activity in the open source world.

The charts shown on a user's profile can provide insight into your open source activity on GitHub, including your typical usage like commits and pull requests. They also include more community-focused aspects such as code reviews and activity in issue trackers in repositories you don't own, which is pretty cool. Whether this information is truly useful or not is up for debate, however, it's no secret that many potential employers out there who consider them a valuable tool when researching interviewees and job candidates:

manuel-frigerio-tweet

Even though I generally disagree with this stance, there's no denying that these charts can play a part in what others perceive of you, and sometimes even what you perceive of yourself. On a more personal note, I find charts like this an effective measure of my drive and motivation; a quiet graph usually means I have either been neglecting some of my open source projects, or I've been too preoccupied to take time to enjoy working on my smaller projects. While they may be a very simple tool, they sometimes come with a very profound message.

Syncing Requirements

You might ask, why another tool?

GitHub appears to be the default site when it comes to discussing these things on social media, however there are many other popular services out there that you might be spending your time on rather than GitHub. Maybe you enjoy having your personal projects on BitBucket, or perhaps your workplace is a fan of GitLab for their automation, etc. Although some of these services also have their own activity charts, it would be great if there were some way to keep them all in sync so your activity actually represents your open source activity, rather than just your activity on a particular service.

I started with an extremely simple use case; I wanted to include the data from my GitLab profile in my GitHub profile, and vice versa. Recall that I use these charts as a measure of my motivation; it would be nice to do this in one place (which would be whichever I am on at the time). There are several tools out there that people have written that cover similar use cases, but as each author has essentially embarked on the same journey on which I have, they all have their own use case in mind and thus their own requirements and features. My requirements are extremely simple:

  1. A vast majority of my open source work lives on GitHub, I must be able to sync GitLab -> GitHub at a minimum.
  2. Ideally all syncs are bi-directional, you can import/export to/from any combination of remote Git services.
  3. I don't want to run this tool manually over and over, I want to run it on a schedule on one of my AWS instances.
  4. I'm not interested in falsifying activity; I want to guarantee the data is accurate as defined by the site's documentation.

Most of the existing tools are pretty good, they generally just fall on my third requirement. Unfortunately, this also happens to be my strictest requirement; I want to configure this and not have to think about it for a long time. If something breaks, I want to be able to fix it, run the tool again, and be up to date. Therefore I decided to write Gitivity, which is a simple CLI to help you sync your Git activity. The initially supported services are as I mentioned above (GitHub and GitLab), although if Gitivity provides popular I will be happy to add support for other services.

The Gitivity API

Gitivity is currently written in JavaScript on top of Node.js. Originally I wanted to use Rust for this project, but the API clients for both GitHub and GitLab are a little green so I went with Node.js for the time being. There's potential for a rewrite in the future, but the API will generally remain the same where appropriate. Gitivity only provides a tiny API, because it does a tiny job.

gitivity export <service> <token>
gitivity import <target>

Rather than let the project snowball, I chose to let Git do all of the heavy lifting - after all, I can assume that all users of Gitivity know at least the basics of Git. I also decided to skip out on any file handling, again because the audience will be familiar with things such as pipes and shell redirecton. Both commands work with stdio; export will emit your activity to stdout while import reads your activity from stdin. This means you can easily do something like this:

gitivity export gitlab glpat-_******************* | \
    gitivity import whitfin/gitlab-activity

Running this will result in a Git repository stored locally at ./whitfin/gitlab-activity, with a commit marked with the appropriate time and date for every action I took on GitLab, These commits are protected from duplication via scanning of the Git log. This means that if I were to run the same command again, it would ensure that new commits would only be generated for activity that was not previously tracked. After the repository has been generated, I can simply go into ./whitfin/gitlab-activity, configure a remote, and push it wherever I want!

Configuring an Activity Sync

Gitivity is written in JavaScript for Node.js, and is compatible with most versions of Node.js (as it really doesn't interact with the system libraries much). As such, it can installed directly from npm, or directly from the GitHub repository.

npm i -g gitivity
npm i -g whitfin/gitivity

Configuring a script to run Gitivity on a schedule is trivial, because the API is so small. As we're just using Git you can also allow for upstream changes to the actual activity repository you're pushing to, so you can easily add a README, or keep notes on how to set it up for yourself, etc. This is done via a simple git pull to fetch anything from the configured remote branch before making new commits:

#!/bin/sh

# move to target directory
mkdir -p /path/to/my/repo
cd /path/to/my/repo

# fetch any remote changes
git pull

# run our export and import steps to the current repo
gitivity export gitlab glpat-_******************* | \
    gitivity import ./

# push the changes to the remote branch
git push

You can see it's pretty quick to set this up and get it running - I've had something similar running on an AWS instance for the last couple of weeks (since I started on this project), and it's been working well! If you have any issues, don't hesitate to reach out via the Gitivity repository.

As this project is pretty new, and I'm sure it can be helpful for other uses and services, please feel free to file issues or suggest feedback on the GitHub repository! This was a fun project work on, as I've never really worked with the GitHub GraphQL API - so I'd be happy to add any other features or options that might be useful!