Automating Virtualbox usage on my build script
My main development machine is a Linux1 computer. While I have a Windows computer as my daily driver2, I’ve always found Linux a better development environment; also, having two separate systems allows me to separate personal and professional life and to switch brain gears when it’s work time.
However, since my desktop projects are crossplatform, I also have a small Windows 10 virtual machine pre-configured with all my development tools and with my current project directory mounted, so if I need to test something on the Windows side of things, I can quickly spin it up and run the project there. It’s not the fastest environment, but it does the job.
While this worked perfectly fine for most of my time developing Kobo Highlights, I’ve been trying to automate my release pipeline a bit. While I still don’t need anything fancy like Github Actions and CI (it’s not like I make new releases all that frequently), I wanted to automate my workflow. By the time of release 1.0.0, the process consisted on:
- Manually editing the version on the
pubspec.yamlfile. - Running
fastforge release --name linux-appimageto generate the Appimage - Spinning up the Windows virtual machine
- Running
flutter build windowsthere. - Zipping the folders and moving them to the correct place before uploading them to Github.
- Updating the direct download links on my portfolio’s database to point to new ones.
After a few days of testing and trying options, I decided to go for the simplest route and write a Python script3. While Python has its pros and its cons, it is a language I was already familiar with, easy to write and read, and more than enough for my use case. This beautiful post by Trey Hunner about creating self-contained shebang scripts with uv also got me very excited about the possibilities and, sure enough, a bit of work later, I had a beautifully functional script taking care of most of the workflow. I could now just type ./build.py and it would take care of the version bumping, generating the native, Flatpak4 and Appimage binaries, correctly named, compressed and ready, and updating my projects database. All automated, with proper error handling, progress notifications and logging, and, thanks to uv, the only thing I needed to make sure the dependencies would be always available was typing this at the beginning of the script.
#!/usr/bin/env -S uv run --script
# /// script
# dependencies = [
# "pyyaml",
# "semver",
# "python-dotenv"
# ]
# ///
However, this left the Windows issue. While the Linux side of things now was almost completely automated, building the Windows binary still required me to spin up the virtual machine and run the build command there. Not the end of the world, but a roadblock threatening to destroy my Automation Dreams.
And then I discovered VBoxManage. Most specifically, VBoxManage startvm, which allows the host machine to automatically start up a virtual machine, and VBoxManage run, which allows the host to send commands to the VM once it is on. And there was much rejoicing by me!
It took a bit of trial and error, but now my build script can also take care of the Windows part of the workflow. It can start up my Windows 10 virtual machine (in headless mode, even!), mount the correct folder, compile the program and move the result binary to the correct place, ready to be zipped and distributed by the rest of the pipeline, after what it silently shuts it down. The Windows-side script is even read from a variable on the build.py file at runtime, so everything I need to build everything is contained on a single file and can be easily be edited.
So, while it took a few days of experimentation to get there, now if I have a release ready, I can just run my little script, go rehydrate, and, around six minutes later, I will have a release deployed, the portfolio updated, and will be, in all and all, a happy little bean.
Automation is cool!
-
Fedora, to be specific. Used to be Manjaro for the longest time. ↩
-
For now. Windows 11 is doing everything it can to tempt me to go Linux full time. Great job, Microsoft. ↩
-
I also found, and fell in love with, Taskfile, but it’s a bit overkill for this particular use case. ↩
-
A work on process, but I am getting there. ↩