If you clicked this article for its title, I’m sorry to disappoint you: I’m not writing a Lord of the Rings spin-off based around the Middle-earth adventures of Smeagol’s hobbit cousins. What I am going to do is walk you through how I turned my github profile’s timeline into a working Game of Life that updates daily. So fill up your wizard pipe and join me on this programming adventure!

Here are screenshots of the first few iterations of the final product:

Gliding away through the github feed.

Cligol

The first step on my journey was forging cligol (command-line interface Game of Life), a small C script in charge of churning out the simulations at our request. I don’t usually program C, so I took a page out of Mary Shelley’s doctor’s book and created a little monster out of many corpses I found online.

The trunk of it all comes from a mix between Rosetta Code and this Code Review post. Tidied up for stylistic consistency and with some added storage and debugging capabilities, it ended up like so:

A truncated version of cligol’s main.c file.

The flow of our main function is relatively simple:

  1. Loads a board from a file or creates a new one if non-existent.
  2. Checks the arguments received.
  3. If the first argument, display, is not present or different to 1, we call the move method, which iterates through our grid and generates the results for the next turn of the game. If the display argument is set to one, it goes into the display_loop method, which handles the rendering of the board and controllable options, irrelevant for our current goal.
  4. Writes the new state of our game into a local file for storage.

So once we compile our script (gcc main.c -o cligol), we can call ./cligol to advance our game one turn at a time. The file data/board.txt will be created on the first run, and updated on each subsequent one.

I’ve tweaked the lifted code in order to add a config.h file, where we can set the board’s width, height and a pseudo-boolean flag to indicate whether our board should behave as a toroidal surface or not. This seemed like a nice addition, since the grid of github is pretty limited and our lifeforms would glide out of our 7 by 52 board rather quickly without it.

At this point, we have a working CLI program which will create and update a file with a format similar to the following:

0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1

Now it’s time to hack a long and dirty bash script that can turn this file’s contents into a beautiful, green-shaded grid in our github profile.

Gifeegol

Enter gifeegol (Github Feed Game of Life), our cligol-calling, file-reading, commit-spamming, default-branch-changing bash script. That description explains in a succinct manner the things our script will need to do, in the order they must be done:

  1. Call cligol to generate a new board, or iterate the existing one into the next turn.
  2. Read the contents of the updated file.
  3. Create a new branch in our repo.
  4. Start iterating through the grid, matching each cell to a particular date.
  5. Whenever the cell value equals one, write 50 commits authored on the matching date. If the value is zero, do nothing.
  6. Push our changes to the new branch.
  7. Patch our repository using github’s API to set the branch we just pushed as the default branch.

The script turned out to be simpler that I had conceived in the beginning, in great part thanks to bash’s date command: initially I was wrongly embarking myself on a path in which the date was handled in a more precarious and manual manner, that led to many lines and ugly code (it can still be seen in the first commits, for the curious).

To be able to run that last CURL request, we first need to generate a public access token from github, which can be easily done from github’s settings. Once we have our token, we can set up a cron to run the script daily, hourly or whenever you see it fit (replacing the $variables and /path/ accordingly):

0 0 * * * USERNAME=$username ACCESS_TOKEN=$token REPOSITORY=$repo /path/to/repo/move.sh

And that’s it, we have a working gifeegol at our disposal!

And back again

I don’t do a lot of bash scripting (and even less coding in C), so I’m sure my code is bug & bad practice ridden. I gladly welcome any and all feedback.

Thanks for reading my first post, I hope you’ve enjoyed it.

About me: I’m a full-stack web developer with over 7 years of experience, currently open to new opportunities. You can check my website for further reference or write directly to me at 1.lucasreta@gmail.com

Written by

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store