Category Archives: Tips and Tricks

Xtext 2.27.0: update your Xbase compiler tests

If you update to Xtext 2.27.0 and have compiler tests for your Xbase DSL that assert the output of the compilation, you’ll get lots of failures after the update.

I am guilty of that ๐Ÿ˜‰
Well, for a good reason, at least ๐Ÿ™‚

In fact, I worked on this issue: https://github.com/eclipse/xtext-extras/issues/772 and its fix is included in Xtext 2.27.0.

Now, the Xbase compilation mechanism does not generate useless empty lines anymore (before, it added lines with two spaces). Your compiler tests will fail because the output is different.

I personally fixed my tests in my DSLs by simply using the Find/Replace mechanism of Eclipse with this substitution pattern (there are two space characters between the tab character and the newline character):

If you have deep nesting in your compilation output, you might have to repeat this substitution with more than two characters, but this should not be required unless you generate nested classes or something like that.

With the above substitution a test like the following one:

will become like the following one (you see the difference: no empty line with two characters between the two generated constructors:

Now your tests should be fixed ๐Ÿ™‚

Configure Arch Pacman

Pacman is the package manager in Linux Arch and Linux Arch-based distributions.

I’ve been using EndeavourOS for some time, and I enjoy it. EndeavourOS is pretty close to vanilla Arch. I also experimented with pure Arch (more on that in future blog posts). However, the output of pacman in EndeavourOS is much more excellent and “eye candy” than in Arch. However, it’s just a matter of configuring /etc/pacman.conf a bit in Arch to have the “eye candy” output.

These are the options to enable in the [options] section in that file (the ParallelDownloads does not have to with the output, but it’s a nice optimization):

Without these options, this is the output of pacman (e.g., during an upgrade):

And this is the output with the options above enabled:

Besides the colors, you can spot c’s for the progress representing “Pacman,” the video-game character, eating candies (that’s the aim of the option ILoveCandy)… waka waka waka!ย  ๐Ÿ™‚

The colors are also helpful when searching for packages:

Happy Pacman! ๐Ÿ™‚

macOS: switch between different windows of the same application

Maybe this is well-known to macOS users, but it wasn’t clear to me as a Linux user.

As a Linux user, I’m used to using Alt+Tab to switch between different windows. But I also use the shortcut to switch between different windows of the same application. In Gnome, the shortcut is Alt+<the key above Tab>, which is cool because it works with any keyboard layout. In KDE it is Alt+backtick (`), which has to be changed in Italian keyboards, like mine to Alt+\. Indeed, in the Italian keyboard layout, the key over tab is \.

In macOS it’s the same as in KDE: the shortcut is bound by default to โŒ˜+`, which of course it’s unusable in Italian keyboards (you should use a complex combination of keys only to insert the backtick ` character). You then have to configure the shortcut “Move focus to next window”, which is quite counterintuitive to me (I had always thought that it wasn’t possible in macOS to switch between windows of the same application if not by using the touchpad gesture or by pressing the down key after using the standard switcher):

Change it to something suitable for your keyboard layout. For the Italian layout I change it to โŒ˜+\:

And then you’re good to go! ๐Ÿ™‚

Dropbox and Gnome 42

Now that Gnome 42 has been released and available in most Linux distributions, I started experiencing problems with the Dropbox icon in the system tray.

First of all, I have no problem with Ubuntu 22.04, which comes with the extension “AppIndicator and KStatusNotifierItem Support” https://extensions.gnome.org/extension/615/appindicator-support/. Moreover, I think the problem is not there because, while Ubuntu 22.04 ships Gnome 42, it still ships Nautilus in version 41.

In Fedora and EndeavourOS, I usually install the same extension in the Gnome DE, and it has been working quite well.

Unfortunately, with Gnome 42 (provided by Fedora 36 and currently by EndeavourOS), I started experiencing problems, even with the extension above installed and activated.

If you had already installed Dropbox in your Gnome 41 DE and upgraded to Gnome 42 (e.g., you upgraded Fedora 35 to Fedora 36 after installing Dropbox), the icon is clickable. Still, you get a context menu always saying “Connecting…”

At least you can access “Preferences…”.

However, suppose you had never installed Dropbox in that Gnome 42 environment. In that case, the icon in the system tray appears (again, after installing the above extension), but no matter how you click on that, no context menu appears at all. That’s a disgrace because you cannot access Dropbox preferences, like “selective sync” (you have to use the command line, as I suggested in the previous post).

Instead of the extension “AppIndicator and KStatusNotifierItem Support” (disable it if you had already activated that), you can use the extension “Tray Icons: Reloaded,” https://extensions.gnome.org/extension/2890/tray-icons-reloaded/. Install it, activate it, logout and login, and now the context menu works as expected:

Remember that this extension does not seem to support all system tray icons. For example, Variety does not seem to be supported.

At least you can use this extension to set up Dropbox (e.g., selective sync) and then go back to the previous extension!

Problems with Linux 5.13 in LG GRAM 16

I recently bought an LG GRAM 16 and I really enjoy that (I’ll blog about that in the near future, hopefully). I had no problems installing Linux, nor with Manjaro Gnome (Phavo) neither with Kubuntu.

However, in Manjaro Gnome I soon started to note some lags, especially with the touchpad and some repainting issues. I had no problems with Kubuntu (it was 21.04). The main difference was that Manjaro was using Linux kernel 5.13, while Kubuntu 21.04 was using Linux kernel 5.11. As soon as I updated to Kubuntu 21.10, which comes with Linux kernel 5.13, I started to have the same problems also in Kubuntu.

Long story short: switching to Linux kernel 5.14 on both systems solved all the problems ๐Ÿ™‚

In Manjaro you can use its kernel management system. Alternatively, from the command line, you can run

On (K)ubuntu things are slightly more complicated because the current version 21.10 does not provide a package for kernel 5.14.

However, you can manually download the DEB files of the kernel (and kernel headers) from the mainline repository https://kernel.ubuntu.com/~kernel-ppa/mainline/. Then, you run dpkg -i on all such downloaded files. However, I prefer to use a nice GUI for such mainline kernels, mainline, https://github.com/bkw777/mainline. It’s just a matter of adding the corresponding PPA repository and installing it:

The GUI application is called “Ubuntu Mainline Kernel Installer”. You select the kernel you want (in this case I’m choosing the latest version of the stable 5.14 version) and choose Install. Reboot and you’re good to go ๐Ÿ™‚

Fixing Right Click Touchpad in PineBook Pro

I recently bought a PineBook Pro (maybe I’ll review it in the future in another post). What annoyed me first was that the right click on the touchpad with a two-finger tap was basically unusable: you should be extremely fast.

In some forums, the solution is to issue this command

but then you have to make it somehow permanent.

Actually, it’s much easier than that: just use the KDE Setting (Tap Detection,ย Maximum time), and this will make it permanent right away:

Caching dependencies in GitHub Actions

I recently started to port all my Java projects from Travis CI to GitHub Actions, since Travis CI changed its pricing model. (I’ll soon update also my book on TDD and Build Automation under that respect.)

I’ve always used caching mechanisms during the builds in Travis CI, to speed up the builds: caching Maven dependencies, especially in big projects, can save a lot of time. In my case, I’m mostly talking of Eclipse plug-in projects, built with Maven/Tycho, and the target platform resolution might have to download a few hundreds of megabytes. Thus, I wanted to use caching also in GitHub Actions, and there’s an action for that.

In this post, I’ll show my strategies for using the cache, in particular, using different workflows based on different operating systems, which are triggered only on some specific events. I’ll use a very simple example, but I’m using this strategy currently on this Xtext project: https://github.com/LorenzoBettini/edelta, which uses more than 300 Mb of dependencies.

The post assumes that you’re already familiar with GitHub Actions.

Warning: Please keep in mind that caches will also be evicted automatically (currently, the documentation says that “caches that are not accessed within the last week will also be evicted”). However, we can still benefit from caches if we are working on a project for a few days in a row.

To experiment with building mechanisms, I suggest you use a very simple example. I’m going to use a simple Maven Java project created with the corresponding Maven archetype: a Java class and a trivial JUnit test. The Java code is not important in this context, and we’ll concentrate on the build automation mechanisms.

The final project can be found here:
https://github.com/LorenzoBettini/github-actions-cache-example.

This is the initial POM for this project:

This is the main workflow file (stored in .github/workflows/maven.yml):

This is a pretty standard workflow for a Java project built with Maven. This workflow runs for every push on any branch and every PR.

Note that we specify to cache the directory where Maven stores all the downloaded artifacts, ~/.m2.

For the cache key, we use the OS where our build is running, a constant string “-m2-” and the result of hashing all the POM files (we’ll see how we rely on this hashing later in this post).

Remember that the cache key will be used in future builds to restore the files saved in the cache. When no cache is found with the given key, the action searches for alternate keys if the restore-keys has been specified. As you see, we specified as the restore key something similar to the actual key: the running OS and the constant string “-m2-” but no hashing. This way, if we change our POMs, the hashing will be different, but if a previous cache exists we can still restore that and make use of the cached values. (See the official documentation for further details.) We’ll then have to download only the new dependencies if any. The cache will then be updated at the end of the successful job.

I usually rely on this strategy for the CI of my projects:

  • build every pushes in any branch using a Linux build environment;
  • build PRs in any branch also on a Windows and macOS environment (actually, I wasn’t using Windows with Travis CI since it did not provide Java support on that environment; that’s another advantage of GitHub Actions, which provides Java support also on Windows)

Thus, I have another workflow definition just for PRs (stored in .github/workflows/pr.yml):

Besides the build matrix for OSes, that’s basically the same as the previous workflow. In particular, we use the same strategy for defining the cache key (and restore key). Thus, we have a different cache for each different operating system.

Now, let’s have a look at the documentation of this action:

A workflow can access and restore a cache created in the current branch, the base branch (including base branches of forked repositories), or the default branch. For example, a cache created on the default branch would be accessible from any pull request. Also, if the branch feature-b has the base branch feature-a, a workflow triggered on feature-b would have access to caches created in the default branch (main), feature-a, and feature-b.

Access restrictions provide cache isolation and security by creating a logical boundary between different workflows and branches. For example, a cache created for the branch feature-a (with the base main) would not be accessible to a pull request for the branch feature-b (with the base main).

What does that mean in our scenario? Since the workflow running on Windows and macOS is executed only in PRs, this means that the cache for these two configurations will never be saved for the master branch. In turns, this means that each time we create a new PR, this workflow will have no chance of finding a cache to restore: the branch for the PR is new (so no cache is available for such a branch) and the base branch (typically, “master” or “main”) will have no cache saved for these two OSes. Summarizing, the builds for the PRs for these two configurations will always have to download all the Maven dependencies from scratch. Of course, if we don’t immediately merge the PR and we push other commits on the branch of the PR, the builds for these two OSes will find a saved cache (if the previous builds of the PR succeeded), but, in any case, the first build for each new PR for these two OSes will take more time (actually, much more time in a complex project with lots of dependencies).

Thus, if we want to benefit from caching also on these two OSes, we have to have another workflow on the OSes Windows and macOS that runs when merging a PR, so that the cache will be stored also for the master branch (actually we could use this strategy also when merging any PR with any base branch, not necessarily the main one).

Here’s this additional workflow (stored in .github/workflows/pr-merge.yml):

Note that we intercept the event push (since a merge of a PR is actually a push) but we have an if statement that enables the workflow only when the commit message contains the string “Merge pull request”, which is the default message when merging a PR on GitHub. In this example, we are only interested in PR merged with the master branch and with any branch starting with “experiments”, but you can adjust that as you see fit. Furthermore, since this workflow is only meant for updating the Maven dependency cache, we skip the tests (with -DskipTests) so that we save some time (especially in a complex project with lots of tests).

This way, after the first PR merged, the PR workflows running on Windows and macOS will find a cache (at least as a starting point).

We can also do better than that and avoid running the Maven build if there’s no need to update the cache. Remember that we use the result of hashing all the POM files in our cache key? We mean that if our POMs do not change then basically we don’t expect our dependencies to change (of course if we’re not using SNAPSHOT dependencies). Now, in the documentation, we also read

When key matches an existing cache, it’s called a cache hit, […] When key doesn’t match an existing cache, it’s called a cache miss, and a new cache is created if the job completes successfully.

The idea is to skip the Maven step in the above workflow “Updates Cache on Windows and macOS” if we have a cache hit since we expect no new dependencies are needed to be downloaded (our POMs haven’t changed). This is the interesting part to change:

Note that we need to define an id for the cache to intercept the cache hit or miss and the id must match the id in the if statement.

This way, if we have a cache hit the workflow for updating the cache on Windows and macOS will be really fast since it won’t even run the Maven build for updating the cache.

If we change the POM, e.g., switch to JUnit 4.13.1, push the change, create a PR, and merge it, then, the workflow for updating the cache will actually run the Maven build since we have a cache miss: the key of the cache has changed. Of course, we’ll still benefit from the already cached dependencies (and all the Maven plugins already downloaded) and we’ll update the cache with the new dependencies for JUnit 4.13.1.

Final notes

One might think to intercept the merge of a PR by using on: pull_request: (as we did in the pr.yml workflow). However, “Thereโ€™s no way to specify that a workflow should be triggered when a pull request is merged”. In the official forum, you can find a solution based on the “closed” PR event and the inspection of the PR “merged” event. So one might think to update the pr.yml workflow accordingly and get rid of the additional pr-merge.yml workflow. However, from my experiments, this solution will not make use of caching, which is the main goal of this post. The symptoms of such a problem are this message when the workflow initially tries to restore a cache:

Warning: Cache service responded with 403

and this message when the cache should be saved:

Unable to reserve cache with key …, another job may be creating this cache.

Another experiment that I tried was to remove the running OS from the cache key, e.g., m2-${{ hashFiles(‘**/pom.xml’) }} instead of ${{ runner.os }}-m2-${{ hashFiles(‘**/pom.xml’) }}, and to use a restore accordingly key, like m2- instead of ${{ runner.os }}-m2-. I was hoping to reuse the same cache across different OS environments. This seems to work for macOS, which seems to be able to reuse the Linux cache. Unfortunately, this does not work for Windows. Thus, I gave up that solution.

Grub remembers the last choice

In all my computers I have dual boot, Ubuntu and Windows, though I’m using the former 99% of the time ๐Ÿ˜‰ On one of my laptop I started to evaluate also Manjaro (probably a blog post will come in the near future). I let Manjaro install the main efi grub boot loader and I noticed that upon reboots its grub configuration remembers the last choice! That is, if I booted Ubuntu (not the first choice in the menu) and I reboot then “Ubuntu” entry is the one selected by default. The same holds for Windows.

I find this feature really cool and useful:

  • if I had previously used Ubuntu and possibly hibernated the computer, then, even after a few days, when I boot the laptop I know which OS I had booted the last time;
  • if I boot Windows (…once in a month?) I will probably experience many updates which require a few reboots; if I left the computer unattended during rebooting I used to find myself back to Linux (the primary default choice in grub) and I had to reboot and choose Windows so that updates are installed (if Windows updates require a few reboots that’s quite annoying).

I thought that Manjaro had some special tweaks in the installed grub, but then I learned that’s a standard feature of Grub!

You just have to add these two lines in your /etc/default/grub:

Save and run

And that’s all! From then on Grub will remember your last choice ๐Ÿ™‚

Remove SNAPSHOT and Qualifier in Maven/Tycho Builds

Before releasing Maven artifacts, you remove the -SNAPSHOT from your POMs. If you develop Eclipse projects and build with Maven and Tycho, you have to keep the versions in the POMs and the versions in MANIFEST, feature.xml and other Eclipse project artifacts consistent. Typically when you release an Eclipse p2 site, you don’t remove the .qualifier in the versions and you will get Eclipse bundles and features versions automatically processed: the .qualifer is replaced with a timestamp. But if you want to release some Eclipse bundles also as Maven artifacts (e.g., to Maven central) you have to remove the -SNAPSHOT before deploying (or they will still be considered snapshots, of course ๐Ÿ™‚ and you have to remove .qualifier in Eclipse bundles accordingly.

To do that, in an automatic way, you can use a combination of Maven plugins and of tycho-versions-plugin.

I’m going to show two different ways of doing that. The example used in this post can be found here: https://github.com/LorenzoBettini/tycho-set-version-example.

First method

The idea is to use the goal parse-version of the org.codehaus.mojo:build-helper-maven-plugin. This will store the parts of the current version in some properties (by default, parsedVersion.majorVersion, parsedVersion.minorVersion and parsedVersion.incrementalVersion).

Then, we can pass these properties appropriately to the goal set-version of the org.eclipse.tycho:tycho-versions-plugin.

This is the Maven command to run:

The goalย set-version of the Tycho plugin will take care of updating the versions (without the -SNAPSHOT and .qualifier) both in POMs and in Eclipse projects’ metadata.

Second method

Alternatively, we can use the goalย set (with argument -DremoveSnapshot=true) of the org.codehaus.mojo:versions-maven-plugin. Then, we use the goal update-eclipse-metadata of the org.eclipse.tycho:tycho-versions-plugin, to update Eclipse projects’ versions according to the version in the POM.

This is the Maven command to run:

The first goal will change the versions in POMs while the second one will change the versions in Eclipse projects’ metadata.

Configuring the plugins

As usual, it’s best practice to configure the used plugins (in this case, their versions) in theย pluginManagement section of your parent POM.

For example, in the parent POM of https://github.com/LorenzoBettini/tycho-set-version-example we have:

 

Conclusions

In the end, choose the method you prefer. Please keep in mind that these goals are not meant to be used during a standard Maven lifecycle, that’s why we ran them explicitly.

Furthermore, the goalย set of the org.codehaus.mojo:versions-maven-plugin might give you some headache if the structure of your Maven/Eclipse projects is quite different from the default one based on nested directories. In particular, if you have an aggregator project different from the parent project, you will have to pass additional arguments or set the versions in different commands (e.g., first on the parent, then on the other modules of the aggregator, etc.)

Installing KDE on top of Ubuntu

If you like to use KDE you probably install Kubuntu directly, instead of Ubuntu, which has been based on Gnome for a long time now.

However, I like to have several Desktop Environments, and, now and then, I like to switch from Gnome to KDE and then back. Currently, I’m using Gnome for most of the time, that’s why I install Ubuntu (instead of Kubuntu).

In any case, you can still install KDE Plasma on top of Ubuntu. The following has been tested on an Ubuntu Disco 19.04, but I guess it will work also on previous distributions.

For a reduced installation of KDE you might want to install only these packages

In particular, kwin-addons includes some useful things: it contains additional KWin desktop and window switchers shipped in the Plasma 5 addons module.

When installation has finished you may want to reboot and then, on the Login screen, you can use the gear icon for specifying that you want to enter the KDE Plasma environment instead of the default Gnome environment.

The above packages should provide you with enough stuff to enjoy a Plasma experience, but it lacks many (K)ubuntu configurations and addons for KDE.

If you want more Kubuntu stuff, you might want to install the “huge” package:

And then you get a real Kubuntu KDE Plasma experience.

Note that this will replace the classic Ubuntu splash screen when booting the OS: it replaces it with the Kubuntu splash screen. If you want to go back to the original splash screen it’s just a matter of removing the following packages:

Remember that you can also use the Kubuntu Backport PPA for enjoying more recent versions of KDE software.

Enjoy Gnome and KDE! ๐Ÿ™‚