Thursday, August 31, 2017

500 Commits of Summer: My story of FOSS and GSoC | MusicBrainz Blog

This story of summer started in a dull grey winter at home. Bored, I started lingering around IRC channels and much like the Alice of Wonderland, stumbled into the wonderful world of FOSS. Little did I know, it was gonna be one of the best things that happened to me. Below is a story of bugs, PRs , repos, commits, and some more commits. But it is also a story of curiosity, learning, frustrations (a lot of it), resilience (more than you think) and some amazing amazing people of the community. If I have to sum it up for you, I couldn’t think of a way better than this. So here it goes…

Disclaimer: It was a long journey, hence the long blog.

The Story

#1: PICARD-851: Correctly update parent items on save

I started out slow. Figuring things out. Picard has a nicely organized and pretty code-base in python. Something that I have always admired and what motivated me to contribute to this project. I went through the tickets and found something I figured I could fix. It took me a complete day to figure my head around the code. Although there was a time when I felt helpless and was about to lose my patience, I was finally able to find where the logic broke and fix it. It felt amazing making my first contribution to Picard.

#7: PICARD-546,287: Add support for tag removal

My first big pull request, where I was actually implementing a feature rather than fixing a bug. The entire pull request took a week to complete including the code reviews. I had to delve and add code across the file and tag handling module of Picard.

#120: Return empty metadata instead of empty dictionary

It was finally a month since I had started contributing to Picard. One of my biggest motivations to contributing regularly was this post by our org admin ruaok before the start of GSoC ’15. I wanted to hold myself to the same standard, and so I did: 1 PR a day. I was quickly fixing up as many tickets as I could, making sure I kept my mentor, zas’ hands full with code reviews. Everyday was exciting for me as I would skim through Jira looking for tickets I could fix for the day. I managed to fix over 20 tickets in my first month.

#228: Add Picard 1.4 release notes

It was Valentine’s Day and man oh man was it a memorable day for my code-valentine – Picard. We finally released a major Picard version after more than 2 years and over 1000 commits. I also got featured on the release blog post, something that made me feel really proud of all the work I had done so far. This was also the time that I had started to visualize how my GSoC project would look like. I started pitching proposals of a v2 for Picard and I got a lot of support for the direction that I wanted to head in. If you want a detailed look into what my final GSoC proposal looked like, it can be seen on the MetaBrainz Community Forum.

#249: Merge pull request #632 from lalinsky/master

A few days, later another surprise awaited me – I finally got push access to the main Picard repo. This was the first pull request I merged. This pull request along with PR #633 was my first time foraying into the world of cross-platform issues. This I believe is the first OSX related bug I fixed, with help from luks and his trusty ol’ Mac. After hours of remote sessions on the Mac that luks had setup for me, we were finally able to resolve a nasty bug that was affecting the OSX build.

#279: Update Qt5 port

This was around the time that I had started to work according to my proposal. We had already released Picard 1.4.1 to fix day 0 bugs that came with 1.4. The development efforts had started to shift toward Picard 2.0.

The first major GSoC task was up: porting the entire code base to Qt5.

It took a mammoth of a pull-request and multiple subsequent patches to finally have Picard up and running on Qt5. Major challenges to this port was the lack of documentation on porting for PyQt5. Apart from the PyQt porting guide, I also had to rely on the Qt5 porting guide written for C++ and figure out the equivalent python bindings. Lucky for me, the guys over at Riverbank (the people who made the PyQt bindings) have done a wonderful job at keeping the bindings as close to the C++ API as possible. This along with stack-overflow and the wonderfully documented Qt5 code, made the porting job much much easier.

Another challenge that I faced was making sure that the above code passed tests on our CI. Picard uses Travis CI, which uses Ubuntu 14.04 containers to build the code. Unfortunately, 14.04 does not have the PyQt5 package for Py2 and building it from source takes forever. As a result, I had to dockerize the repo and run the tests in Ubuntu 16.04 in docker in a Trusty container over at Travis CI. Talk about code-ception.

#280: Replace deprecated __builtin__

Next task on my GSoC checklist was equally big. I had to port all of the code to Python 3. I was targeting Python 3.5 for the port. Of much help to me this time were the Python tools, pylint and python-modernize. I used them to figure out the pieces of Python version 2 code that had been deprecated and to replace them with equivalent Python 3 code. Major part of the problems I faced here were encoding issues. And believe me, they only get magnified if your app is cross-platform and multilingual.

Couple the above with PyQt5 behaving slightly differently for Python 3 compared to Python 2, I had to plow through a lot of encoding/decoding/string/bytes issues. Pile Mutagen (a Python audio tagging library that Picard depends on) on top of this mess and you have a recipe for an encoding/decoding disaster.

After lots of string/byte fixes and banging my head against the wall porting this black magic code, I finally managed to port Picard to Python 3 with all tests passing. \o/

You can find all the above commits in this massive PR.

#382: Update setup script to allow submitting pip packages

Next, to weed out further bugs, I wanted as many alpha testers as possible. To make their task easier, I packaged Picard into a pip package and released it on PyPi.

#393: PICARD-817: Enable high DPI support for Picard

I further tackled the issue of Picard not rendering properly on High-DPI screens. This issue mainly affected our OSX users and with the port to Qt5, it was easy to alleviate. Although not mentioned explicitly in the Qt5 documentation, I was able to find a couple of blog posts that helped me successfully implement it. Basically I needed to add up-scaled versions of the icons used by Picard in the Qt resources with a special suffix and Qt took care of the rest.

Since the upscaled version of the icons used by Picard were missing, I ended up designing an entirely new icon-set for Picard myself. This was my first time with tweaking with Inkscape, but I think I managed fine.

#404: Add coverage reports for codacy

Part of my GSoC project included testing the Picard code extensively. To help me get on with it, I set up Codacy on the Picard repository to display coverage and linting issues for all builds. This really helped with reviewing code and keeping contributions to the Picard repo clean and upto the quality that is expected. Coverage reports also allowed us to figure out which key pieces of Picard code was untested and target them to ensure there were as less regressions as possible.

#442: Migrate code to json API

My next big challenge was moving the webservice API calls from XML to JSON. Initally it meant refactoring the spaghetti code that was the Picard webservice module. I untangled the code and split it into an easy to add upon WebService and APIHelper classes.

Next came the actual porting part. I had to manually figure out the differences in the JSON and XML outputs of all the APIs used by Picard (mainly the MusicBrainz API and the AcoustID API).

This port also helped in figuring out the parts of MB JSON API that were missing or behaving differently from the XML API. Bitmap, our resident MB developer was quick to fix all the issues blocking the transition to the JSON API for Picard. Picard switching to the JSON API also served as a good way to test our upcoming MB WebService 2.5, that is supposed to be JSON only.

#485: Add appveyor config for windows tests

Testing a cross-platform app means you need to get your hands dirty on all 3 OSes. Primarily a Linux user, I had to blindly write CI configs for Windows and OSX. For Windows testing, I have not yet found a better platform than AppVeyor. It is free for FOSS projects and down-right amazing in terms of queuing and build speeds.

I didn’t have any options when it came to OSX builds. Although Travis does provide the functionality, the number of OSX containers available are scarce compared to the number of jobs that get submitted. As a result, I faced long queuing times which made the blindly-writing-configs-and-using-Travis-to-test part very difficult. I managed to do it with a wee bit of patience and the fact the OSX has bash.

#500: Add v2 plugin manifest compatibility

All was well and I was finally on the last step of my GSoC project. All that remained was tidying up the code, fixing any remaining bugs and switching to a more robust plugin packaging and distribution API. I wrote a CLI tool for the same, which you can find here.

Link to all the above commits: 500 Commits of Summer


By some stroke of fate, my total commits to the Picard repository are exactly 500 in number as of this post. I shook my head in disbelief and amazement as I let it sink in. I have come a long, long way. During this entire journey, I have learnt a lot of new things: version control, making cross-platform desktop applications, proper unit-testing, i18n, CI, making CLI tools, designing APIs, documenting and reviewing code and most of all writing modular, manageable and maintainable code.



Frankly, I would’ve never expected last year that my GitHub would look so green. I have made over 1200+ contributions this year to FOSS. My coding skills have taken a giant leap from last year. I would recommend every coder to try and contribute to a large open-source project at least once during their lifetime. It teaches you a lot of things that can frankly never be taught anywhere else, and the entire experience is totally worth it!

GSoC is a marvellous platform to incubate contributors to the open-source world. I want to thank my mentor zas (Laurent Monin) and my org admin ruaok (Robert Kaye) for helping me throughout and making sure I had an amazing GSoC experience, and Google for making this possible.

This has been an amazing opportunity for me. The MetaBrainz community has been nothing short of wonderful to me and I am looking forward to contributing more to MetaBrainz and exploring other FOSS projects.


No comments: