TLDR

Applications in snaps running script to call other electron snapped application do not mix well.

Final solution, was use old tools like incrond to captures the changes in the diagrams to auto generate the files.

Story

💡

My first thought was to create a GitHub Action to generate these files, but actions-drawio is based in code it is archived, because drawio-desktop already supports command line interface to export to image formats.

Some time ago, skimming git documentation I saw references for hooks and this time, was a good time to try it out. Each time I commit a new diagram, it will auto generate a new image.

It could not to be to difficult to do a simple script to do this task… and… oh god! how wrong I was.

Hurdle ① - Snap Confinement and drawio-desktop

Snap Confinement is good for the security of our computers, but, it expects users have their files in the default locations, and, almost all my files are not.

So I try to use the trick to remount my working directory inside /mnt to allow snap removable-media interface to use it, but no luck.

$ sudo snap connections drawio | grep removable-media
$

Solution

Modify the snap to add the removable-media interface

$ snap download drawio
$ unsquashfs -dest drawio_138 drawio_138.snap

Edit drawio_138/meta/snap.yaml and add removable-media into plugs

Resulting in something like:

apps:
drawio:
    command: command.sh
    plugs:
        (...)
        - opengl
        - removable-media
    environment:

Then, use the modified snap with snap try

$ sudo snap try drawio_138

Snap, installed

$ snap list 
Name                             Version                     Rev    Tracking         Publisher          Notes
core20                           20211129                    1270   latest/stable    canonical✓         base
drawio                           16.0.2                      x1     -                -                  try

Last task, mount the directory in the new location, adapted from Home directories outside of ‘/home’

# mount --bind  /work/WIP/ /mnt/WIP/

Hurdle ② - Git Hooks

I’m new to git, so, choose the right hook to do the task, was not easy… some voices in internet, say to use pre-commit, but adding files at this stage is not linear.

My chosen solution was to do a post-commit, in which will generate the file and then add and commit the file. Something like:

/snap/bin/drawio --export 
git add
git commit -m "AutoCommit - Update DrawIO Images" 

I made the script work when I manually ran git commit on terminal… but when the hook ran inside VSCodium… it didn’t work…

Hurdle ③ - Electron… Snaps…

From inside an Electron App (VSCodium) try to run another Electron App (drawio-desktop), was an hell, so I quit to make it work.

Just a quick note, if you see something like this in your system logs

kernel: traps: drawio[767435] trap int3 ip:55fac191b086 sp:7ffe0bb228d0 error:0 in drawio[55fac0bcb000+6a10000]

Consider it as a core dump.

Hurdle ④ - No Git Hooks

Without git hooks, I need to find a solution to detect file changes, and inotify kernel feature is a great solution, but lack a good user land tools.

inotifywait paired with while, as many solutions out there, was not an option…

Just found to possible paths:

incron

systemd.path

  • 👍 I would like to use StartLimitIntervalSec and StartLimitBurst, because, drawio-desktop after each change saves the file.
  • 👎🏼 How to tell which PathChanged?

Do not have an option to have the name of the modified file, kills the possibility to use systemd.path, I do not know how many files and directories I will have in the end, and manage all manually, will kill the agility.

So in the end, I just have the option of incron 😒

Hurdle ⑤ - Electron is not meant to run on headless

Electron apps are made to be used in a graphical environment, not to be used in a script.

But fortunately, someone use CICD process to test their electron app already have that problem solved.

Meanwhile, feature request in electron is not done, we have an option to create a Xvfb

Solution

Install and configure incron

This is the easiest part

$ sudo apt install incron

Then, add your username to /etc/incron.allow

Deploy user configurations

Edit incrontab

$ incrontab -e

and add your configuration

/work/WIP/Clouds/*.drawio  IN_CLOSE_WRITE  /home/johndoe/bin/incron-drawio.sh $@

Then create your script /home/johndoe/bin/incron-drawio.sh

My Script

#!/bin/bash
set -Eeuo pipefail

# because drawio runs as a snap, it can not access the real location of the file
# to be changed as needed
realFile=$( readlink -f "$1" | sed "s#/work#/mnt#" )

lastChange=$(stat --format="%Y" "${realFile%.*}".png)
now=$(date +"%s")
delta=$(( now - lastChange ))

# drawio saves file each time it move an item... ignore changes below 30 seconds
[ $delta -lt 30 ] && exit

echo "incron generating image from $1" | logger 

# drawio is an electron app, and expect to have a display server
# so, use a framebuffer without GPU
export DISPLAY=':99.0'
Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
Xvfb_PID=$!

drawio='/snap/bin/drawio --export --width 1024 --border 10'
$drawio --output "${realFile%.*}".png "$realFile" | logger 

kill $Xvfb_PID

🍬

Some other resources how help me in this journey