Automatically updating Nightly builds of Krita on Linux

When chatting on Krita IRC @deevad mentioned that he uses a script to automatically download Krita nightly update and manage the launcher icons etc. So I thought that it is a cool idea to use script to automate the update. Usually I used to click on the update button and then manually adjust the filename of the appimage etc. I already have different desktop files to launch the appimage. The update done from the welcome screen downloads a file with new file name and we have to either adjust the name in desktop file or rename the downloaded file.

So when searching for a solution to automate this I found out about appimageupdatetool I believe this is the same tool backend that Krita uses to fetch the update too. This tool has a GUI version and also a cli version. I downloaded the cli version which is named appimageupdatetool.

wget  https://github.com/AppImage/AppImageUpdate/releases/download/continuous/appimageupdatetool-x86_64.AppImage -O ~/.local/bin/appimageupdatetool

The above command downloads the binary file of the tool to my computer’s local/bin folder. I then mark it as executable with the following command.

chmod +x  ~/.local/bin/appimageupdatetool

One of the best advantages of using this tool is that it has the option to self update itself and also update the appimage file in place having the same name that you have given the appimage.

So updating an appimage is this command

appimageupdatetool  -rO ~/store/Krita/nightly/krita-nightly

The -r option removes old appimage file and -O option overwrites the old file. It overwrites it by default but also makes a backup file with .old filename so to remove that file we pass the -r option. I have renamed the appimage to “krita-nightly” and my desktop file placed in .local/share/applications/ targets this file. Earlier when a new appimage was downloaded, it had different name on each update I would need to rename the appimage or edit the desktop file with new name.

Below is content of my desktop file called - org.kde.krita-appimage-nightly.desktop

[Desktop Entry]
Categories=Qt;KDE;Graphics;2DGraphics;RasterGraphics;
Comment=Digital Painting
Exec=/home/raghu/store/Krita/nightly/krita-nightly
GenericName=Digital Painting
Icon=/mnt/attic/krita-build/krita/krita/pics/branding/Next/512-apps-krita.png
MimeType=image/openraster;application/x-krita;
Name=Krita-nightly
StartupNotify=true
StartupWMClass=krita
Terminal=false
X-KDE-NativeMimeType=application/x-krita

I have used a different Krita icon with git symbol from Krita repository that I have cloned on my hard disk. I just supplied the path in the Icon option. The Exec option determines the target binary that needs to be launched when you click this desktop file. I gave it the patch where I store the nightly appimage.

Now onto the automation and scripting part

I used my limited knowledge of bash and stack exchange search skills to craft this bash script, which will be run everyday to update Krita using systemd timer.

#!/usr/bin/env bash
# Krita nightly update
# A script to update appimage of Krita

# we first check if the appimagetool itself is up-to-date.
# Rather than checking daily I check only after 25th of every month.
# I could also just check if there is any update with the tool itself but I felt lazy and did this.

cur_day=$(date +%d)  # gets current day from system and assigns it to a variable.

# check for the update of appimageupdatetool itself on 25th of every month

if [ ${cur_day} -ge 25 ];
then
	echo "Checking and updating of appimageupdatetool"
	~/.local/bin/appimageupdatetool -rO --self-update # command to self update the tool
else
	echo "skipping update of appimageupdatetool since it is not 25th yet"
fi

update1=$? # get the exit code assigned to a variable

# updating Krita
echo "Now checking and updating the Krita nightly"
~/.local/bin/appimageupdatetool  -rO ~/store/Krita/nightly/krita-nightly # command to update Krita appimage

update2=$?  # get the exit code assigned to a variable

# use highest exit code as global exit code
global_exit=$(( update1 > update2 ? update1 : update2 ))

# I then send a notification popup on the desktop to let myself know of the result or error. 
# This requires a utility called notify-send which is present in most linux repositories.

if [ ${global_exit} -eq 0 ];
then
	notify-send -a 'Krita update' -h "string:desktop-entry:org.kde.krita" -u normal 'Krita update done' 'No errors & update complete' --icon=face-smile
fi

if [ ${global_exit} -gt 0 ];
then
	notify-send -a 'Krita update' -h "string:desktop-entry:org.kde.krita" -u critical 'Krita update failed' 'check the system journal' --icon=face-sad
fi

exit ${global_exit}

This is a crude script and might be improvised or enhanced. If you have any better method or way of writing it or have any extra additions please suggest. I might change it later when I have lots of procrastination time on hand.

Now comes the part where this script is run daily and automated. Earlier I used to use cron but systemd timers are efficient and handy plus I do not need to install cron as systemd comes with the distro already.

I have enabled something called lingering enabled this helps in running user services without a session although here it won’t be needed I think but the command to enable it is loginctl enable-linger username and then logout and login again.

A user can run a systemd service and the service file need not be in the system directories. There are two files required. A service file which determines what to do and a timer file which determines when to do it. Both files are stored in ~/.config/systemd/user/ folder.

I have a krita-nightly.service file in the above folder which says systemd to run the bash script. The content of the file is:

[Unit]
Description=Krita nightly update
Wants=krita-nightly.timer
 
[Service]
Type=simple
ExecStart=/home/raghu/.local/bin/krita-nightly.sh

The ExecStart=/home/raghu/.local/bin/krita-nightly.sh gives the path of the script to execute.

Now the timer file has the following content and is stored in the same folder mentioned above.

[Unit]
Description=Krita nightly update timer
After=plasma-plasmashell.service # runs after my desktop session is started. use whatever relevant to your desktop environment.
Requires=krita-nightly.service 

[Timer]
OnCalendar=daily # runs the script daily at 24:00 midnight
RandomizedDelaySec=10min # adding a random delay so that this doesn't clash with anything other 
Persistent=true # if my PC is not on at that time this will make sure it is run when I boot next time.

[Install]
WantedBy=graphical-session.target # runs only when I have a GUI session

After I place the two files in the folder, I run the following command to enable and start the timer.

systemctl --user enable --now krita-nightly.timer

This will enable the timer which in turn will run the updating script only for my user account. If the update goes through I get a nice notification on the desktop


if not then the notification says to check the logs for error.

Hope this helps someone who wants to automate the process.

Note: I have nightly and stable builds in separate folder to not hinder the resource files of each version. I also have two desktop launchers for nightly and stable.

6 Likes

That’s a super method! Way simplier than my script. Thank you for sharing :+1:

1 Like

Yeah the main reason I went for appimageupdatetool is because it uses deltas to download. So it won;t download entire file every time. And there is no need to rename or move things. I need to test the systemd timer for triggering only once on boot daily, right now I have made it run after the systemd service of plasma shell.

1 Like

Sorry OP, but I can’t get this working on my Distribution. - The main factor, is because I’m not using KDE Plasma. I’m on MATE DE.
I don’t understand what linger is? I also am not sure if it needs to be run as root or not?
~/.config/systemd/user - didn’t exist, so I had to create it, including the systemd parent dir.

I’m not good with systemd, but I can probably make this work, I’ll just have to do it at a Root level. - Which I don’t want to do, with /lib/systemd/system/

I think for now, I will update manually. When I try to start the Timer, it gives me a STDOUT that something is missing, I also tried to start the service manually via systemctl - but that failed too :frowning:

The command to enable lingering is loginctl enable-linger <your_username> , I do not think root is required for this command. What lingering does is basically allows some process started by systemd as your user to be kept alive even when you log out. I am too not fully expert in systemd, I am not a dev.

Check the journal with journalctl to see what error it gave. Also systemctl status <servicename> will show you the status along with the error it encountered.