TL;DR: I created a tool to help batch-delete repositories from GitHub organizations. You can find the source repository at https://github.com/doctor-g/repo-deleter-flutter.
I have a few GitHub organizations that I re-use every semester. I set them up as through an academic account years ago. At the start of the semester, I add all my current students, and they push their work to repositories within this organization. This way, not only can I easily access students' work, they can also help each other out. For example, we can do peer code reviews in class across organizations without requiring anyone to use public repositories. I can also share all my sample code for the semester in the organization, and only those in the organization can get to it.
The downside to this approach is that the organizations require significant cleanup after a semester ends. Although I always instruct students how to move their work from the class organization into their own accounts, there are inevitably dozens of repositories left unattended. Deleting repositories manually through GitHub's web interface is mindless and tedious. There are a few online tools that claim to support batch-deletion of repositories, but I never had great luck with them.
To make my life a little easier, two years ago, I created a little command-line tool to manage the process. I created it in Dart using the github package, which wraps GitHub's Web API. This little tool required you to go into the source code to modify the organization name and any special rules about which repositories to list. For example, I have had semesters where students had to name their projects in a pattern "PX-username" where X is the project number and username is a BSU username. The tool then had two different paths, which I would comment out alternately: the first printed the names of the repositories that it would delete, and the other would delete those repositories. It was not a great utility, and it needed manual cleanup for the repositories that didn't follow the patterns, but it did save me some manual work on GitHub's Web interface.
After a couple of semesters of dealing with that tool, I decided it was time to make something better, and so today I released Repo Deleter at https://github.com/doctor-g/repo-deleter-flutter. This new version includes a graphical user-interface powered by Flutter. Like its predecessor, it requires using a GitHub personal access token with the appropriate permissions; the details for this are given in the project README file. With the proper credentials in place, Repo Deleter allows you to select one of your GitHub organizations. Then it shows you all of the organization's repositories, both public and private. The user can select any number of these, and then, with the click of a button, delete them.
Repo Deleter screenshot (student names blurred out) |
In addition to solving a proximal problem, there are two technical aspects to this project that I found rewarding. The first and most important one is that this application uses the bloc pattern. I mentioned my experiments with bloc as part of my tinkering with Dart and Flutter for creating tabletop-inspired videogames. That work is hidden away in a handful of private repositories, and because nothing became of them, it was hard to assess my own understanding of the pattern. I used bloc for the Repo Deleter as well, and it felt quite comfortable. I wonder how a bloc expert would critique the particular states and events that I used, but as a proof of concept, it definitely works. I suppose the proof of the pudding may be in six months when I have to open the project again and inevitably want to add a feature or two. Will I be able to read and make sense out of the code? Time will tell.
The less important but still interest aspect of Repo Deleter is that it's the first place where I used a formal logging framework in Flutter. It is not fancy: it's just the stock logging package, and I'm only echoing logs to a print command. Still, it eliminates the compiler warnings I had from the handful of print statements I had peppered in as ad hoc debugging aids.
One thing I would like to have done, but did not, was to have developed it via TDD. My early prototypes used the github package libraries throughout the application, with no adapter layers. Isolating the data layer from the logic layer would have facilitated testing layers without making actual network requests. I had idle hopes of using this as an example for my students, but in the end, I made the decision to just build on a working prototype rather than engineer something more robust.
Right now, the repository only has Linux platform support, but its easy enough to add more using the Flutter tools. I simply run it from Android Studio because it's easy to set an environment variable for a specific run configuration.
No comments:
Post a Comment