I Walked Right Into the YAML Trap
2024-05-19
Today I was creating a Flatpak version of a simple digital painting application that I developed last year, and I walked right into a notorious pitfall that YAML has. Usually these are the kind of silly issues that can cost hours, but thankfully, this time it became apparent within a couple of seconds and left me with an interesting post to share.
Vara is a minimalist digital painting application that has support for pressure-sensitive brushes. I developed a fairly useful version of it last year within a month, as a technology demonstration of nguigen, one of my other projects. I had provided binary tarballs and .deb files right away, as I always do. Then I stopped working on Vara for a while because I had to shift my focus back to some other projects as well as my academic activities.
Recently I became in a position to revisit the project, and realized it was a perfect opportunity to gain hands-on experience on relatively new packaging methods like Flatpak and Snap. I do not have any comments on the technical pros and cons of these compared to the traditional methods for the time being, but I believe that getting your application on places like Flathub and Snap Store is important in reaching a wider Desktop GNU/Linux userbase.
The Process
I started experimenting with Flatpak building inside Fedora 40 with GNOME inside a VM created using virt-manager. I created a VM because in my experience, Fedora is the best distro to do cutting-edge Gtk/GNOME development. The packages are up-to-date and the whole experience is smooth compared to Debian or even Ubuntu. This was the first time I used virt-manager; I usually use KVM/Qemu directly or create VMs in my rack server that runs Proxmox. I've been wanting to try something portable and easy like VirtualBox that isn't VirtualBox, but never got GNOME Boxes running on any of the machines I tried, not even once. That's how I decided to give virt-manager a try, and I regret not doing it a bit sooner. It is extremely easy and fast for any basic use case (I don't know about advanced cases).
Thanks to the excellent documentation, I learned the basics of Flatpak creation yesterday, and started working on packaging Vara today. I released Vara's source code as part of it, a step that got delayed only because of tight schedule.
After successful builds and tests, I submitted the package to Flathub. I got first responses within a couple of hours, and the volunteers were really friendly and helpful. The review cycle is still in progress as I write this post.
The Pitfall
Flatpak accepts build commands in the manifest file, and I'd given all my
commands as a one-liner like command1 && command2 && ...
. The
metadata file was in YAML format and the commands could be given as an array. So
one of the reviewers suggested me to break down the commands into multiple lines
(meaning distinct array elements). That was easy, but did Flatpak guarantee that
the build process would terminate when one of the commands failed? The
documentation wasn't saying anything about this (just filed a PR).
I was sure that the reviewer knew what he was talking about, but still, wanted
to try and make sure.
It is easy to perform a test with a command that fails, for Unix provides a command called
false
. So I modified the build-commands
section in
my metadata file from this:
build-commands: - make -C src - install -D -s src/vara /app/bin/vara - cp -r usr/* /app/ - install -D in.co.nandakumar.vara.metainfo.xml /app/share/metainfo/in.co.nandakumar.vara.metainfo.xml
to this:
build-commands:
- make -C src
- install -D -s src/vara /app/bin/vara
- false
- cp -r usr/* /app/
- install -D in.co.nandakumar.vara.metainfo.xml /app/share/metainfo/in.co.nandakumar.vara.metainfo.xml
What happens to the build now? It finishes without any errors! But it should,
for false
is meant to fail. I just ran false; echo $?
to make sure it returns 1
(meaning failure), yet the build
succeeds. Since I wasn't so sure about false
, I decided to try some
command that actually tries to perform something and fails. So I replaced
false
with mkdir /tmp/p/q
which would fail because
/tmp/p
was nonexistent. And this time the build failed, unlike with
false
!
This is when I really started doubting false
. Is it treated
differently because it is a dummy command?
Then it occured to me: YAML is notorious for its interpretation of
true
, false
, yes
, no
, etc.
So the entry false
that I gave as a command was probably being
treated as the Boolean value True. This isn't something that I didn't know, but
false
as an element in a string array getting reinterpreted as bool
caught me off-guard.
Why Flatpak Builder was unable to detect an element being a different type is
another question that I do not want to get into now. All I wanted to share in
this post was an interesting case of YAML Boolean gotcha that might cause one to
misjudge the behaviour of programs, including basic and well-known commands like
false
.
NOTE: Flatpak supports JSON as well; I went for YAML simply because the official tutorial was using it.
Nandakumar Edamana
Tags: pitfalls, yaml, vara, flatpak, fedora, gnome, experience
Read more from Nandakumar at nandakumar.org/blog/