Skip to main content

Iemand zin om mijn code te reviewen?

Laat ons het hebben over code review. Waarschijnlijk bestaan er verschillende definities van 'code review', ik zal eerst even verduidelijken wat ik met code review bedoel.

In grote lijnen: alvorens er aanpassingen gebeuren aan de broncode van je software, is het de bedoeling dat één van je collega's er eens naar gekeken heeft. Zodat die collega vragen kan stellen, of opmerkingen kan maken.

speelkaart en broncode

Read more…

PHP event sourcing aan de kaarttafel

Vandaag ga ik eens wat dieper in op de inner workings van WDEBELEK, de webtoepassing die ik schreef om online te kaarten (wiezen en gelijkaardige spelletjes).

Want het is niet alleen erg fijn dat we in tijden van quarantaine en avondklok nog kunnen kaarten, het is ook bijzonder cool dat de achterliggende software gebruik maakt van event sourcing; dat is toch alleszins wat ik probeer.

Mijn bedoeling is om jullie in al dit moois in te leiden aan de hand van de wijzigingen in de code die nodig waren voor een nieuwe feature die ik onlangs inbouwde: het opnieuw open leggen van een slag die eigenlijk al opgeraapt was.

playing cards

Read more…

Quarantaine whist with WDEBELEK

Now that the daily number of new COVID-19 infections is increasing, and people are talking about the possibility of local lockdowns, chances increase that card playing evenings will be canceled because of corona reasons.

But, as opposed to the previous lockdown, now there is an easy solution to play solo whist remotely. Because I work on a web application for online card playing: WDEBELEK.

It is still a young application, with a lot of loose ends, but it has been tested extensively, and it seemed to be useful. How does it work:

  1. Find 3 to 5 friends that want to play cards with you.
  2. Start a video conference with these friends, using your favourite video conferencing tool.
  3. Create a card table at
  4. Create invitation links, and pass them on to your friends.
  5. Play cards!

We do have a basic manual, but that's in Dutch. (If anybody wants to translate it to English: let me know.) Anyway, the use of the application should be straight forward.

Source code is freely available under the conditions of the AGPL v3 or later. And you can use the software for fee; that is: as long as my server can handle the load.


kaarten in quarantaine

Selenium web tests on gitlab-ci for an app using Mercure

I recently learned how to use Mercure so that the php/Symfony back-end of my application can send out events that can be picked up by the javascript on my front end. This is really cool technology, you should definitely try this out if you haven't already done so.

Now if you write this kind of software, of course you also want to write some web tests, so that you can automatically check if existing features of your program keep working after you add new things.

gitlab-ci, codeception and mercure

For these kind of tests, I use gitlab-ci and codeception, as I wrote in previous posts. Today I got these test working with a Mercure hub.

You need to use a mercure service in the job running your web tests, which you can configure in .gitlab-ci.yml:

Update 2020-12-03: I use the 0.10 version of the mercure container, because the acceptance test job started failing with 0.11, with these error messages:

Message: "Couldn't connect to server for "http://mercure:3000/.well-known/mercure"." In HandleMessageMiddleware.php line 80:

Couldn't connect to server for "http://mercure:3000/.well-known/mercure".)

So here's the adapted .gitlab-ci.yml-file:

  JWT_KEY: YourSecretKey
  DEMO: 1
  ADDR: ':3000'

# ...

acceptance tests:
  # I would prefer to use a public php-7.3 image with mysqli, but
  # I don't think such a thing exists.
  # So let's reuse the image I created for the dikdikdik web tests.
    - name: mariadb:10.4
      alias: db
    - name: selenium/standalone-chrome
      alias: chrome
    - name: dunglas/mercure
      alias: mercure:v0.10
  # (the rest of the job follows here)

The JWT_KEY should work with the JWT your backend uses to publish events. The port number in ADDR as well. If you use Symfony, as I do, the corresponding configuration of your backend should be in the .env file, e.g.


(Needless to say: don't use the production JWT and token in the source code that is used by gitlab! If you're unsure how to create a JWT, see the section ‘Creating your JWT’ of this excellent blog post.)

Update 2020-12-03: That blog post doesn't exist anymore, but I found another page that covers mercure and the JWT token.

Now the problem I ran into, is similar to the general problem I had with web tests: the chrome container doesn't know where the mercure hub is; the host name ‘mercure’ is not resolved to an ip address.

To fix this, I figure out the IP address of the Mercure hub when I start the job, and I replace the host name of the MERCURE_PUBLISH_URL in the .env file by this IP-address. This works, since my frontend retrieves the publish url from the backend by a rest-call.

This is how that looks like:

    - MERCURE_IP=$(getent hosts mercure | awk '{ print $1 }')
    - echo Mercure IP $MERCURE_IP
    - sed -i "s/mercure:3000/$MERCURE_IP:3000/" .env

You can review the complete job definition in the .gitlab-ci.yml file in the wdebelek repository. The file acceptance/TrickCest.php contains an example test involving server sent events. And hopefully you can see in the pipelines that all tests passed without problems 🤓.

Dependency hell when upgrading symfony from 4.3 to 4.4

Recently I tried to upgrade the symfony version of the dikdikdik wiezen score app from 4.3 to 4.4. As usual, I ended up in dependency hell.

Here's what I got:

$ composer update symfony/*
Loading composer repositories with package information
Updating dependencies (including require-dev)
Restricting packages listed in "symfony/symfony" to "4.4.*"
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Conclusion: don't install symfony/validator v4.4.7
    - Conclusion: don't install symfony/validator v4.4.6
    - Conclusion: don't install symfony/validator v4.4.5
    - Conclusion: don't install symfony/validator v4.4.4
    - Conclusion: don't install symfony/validator v4.4.3
    - Conclusion: don't install symfony/validator v4.4.2
    - Conclusion: don't install symfony/validator v4.4.1
    - symfony/validator v4.4.0 conflicts with doctrine/lexer[v1.0.1].
    - symfony/validator v4.4.0 conflicts with doctrine/lexer[v1.0.1].
    - symfony/validator v4.4.0 conflicts with doctrine/lexer[v1.0.1].
    - Installation request for symfony/validator 4.4.* -> satisfiable by symfony/validator[v4.4.0, v4.4.1, v4.4.2, v4.4.3, v4.4.4, v4.4.5, v4.4.6, v4.4.7].
    - Installation request for doctrine/lexer (locked at v1.0.1) -> satisfiable by doctrine/lexer[v1.0.1].

I ran composer require doctrine/lexer, hoping that this would give me some clues:

$ composer depends doctrine/lexer
doctrine/annotations  v1.8.0   requires  doctrine/lexer (1.*)
doctrine/common       v2.10.0  requires  doctrine/lexer (^1.0)

I guess that doctrine must have been the problem.

So I uninstalled doctrine (composer remove symfony/orm-pack), upgraded symfony (that worked, 🎉), put the doctrine configuration files back in place, and reinstalled doctrine (composer require symfony/orm-pack).

It did update something, but then I got this error:

Executing script cache:clear [KO]
Script cache:clear returned with error code 255
!!  PHP Fatal error:  Uncaught Symfony\Component\Debug\Exception\ClassNotFoundException: Attempted to load class "DoctrineCacheBundle" from namespace "Doctrine\Bundle\DoctrineCacheBundle".
!!  Did you forget a "use" statement for another namespace?

After some searching on the internet, I found out that I had to remove the line

Doctrine\Bundle\DoctrineCacheBundle\DoctrineCacheBundle::class => ['all' => true],

from app.php to fix that one.

Of course now I had various other issues, but the dependency hell was fixed, so I am glad I can share this with you.

Dikdikdik: a Wiezen (Solo Whist) score app

For some time I've been working on a web application that helps you keeping track of the score if you want to play the Wiezen card game. Wiezen, as we play it, is called solo whist on Wikipedia.

Yesterday this score application (in Dutch, sorry) reached version 1.0. So I thought it would be appropriate to announce this release on my blog.

Admittedly, the user interface leaves a lot to be desired. But it turned out a very cool application (imho), with a nice event sourced backend, and gitlab pipelines that automatically test new source code. 🤓

The score app follows the whist game rules as set by Rijk van Afdronk vzw. The application can be tested (as long as my vps doesn't die) at; source code can be found on gitlab.

can only get this once!

Plastic prullen

Vanmorgen las ik in De Morgen een column waarin Sofie Guns een pleidooi voert tegen plastic rommel, die je op verschillende plaatsen krijgt, als cadeautje voor de kinderen. Of voor jezelf, zo je wil. Het artikel zit achter een paywall, maar de auteur hekelt de dubbelzinnige houding van supermarkten als het op ecologie aankomt. Stoffen zakjes om fruit in mee te nemen kwamen in de plaats van exemplaren in plastic, en herbruikbare tassen worden overal gepromoot. Maar tegelijkertijd delen supermarkten vaak gratis en ongevraagd plastic emoji's, bouwblokjes, en andere brol uit, netjes verpakt in een plastic jasje. Die dingen worden misschien geproduceerd aan de andere kant van de wereld, leggen een hele reis af met boot, vliegtuig en/of vrachtwagen, om hier in het beste geval terug in een vuilnisbak te verdwijnen. Of in het slechtste geval naast de weg, en uiteindelijk in de plastic soup ergens op zee.

Afgelopen weekend zijn we met de kinderen zwerfvuil gaan opruimen in de gemeente. We vonden voornamelijk sigarettenpeuken en lege drankblikjes naast de weg, maar er zat toch ook een aanzienlijke hoeveelheid plastic in onze volle afvalzakken. Dus alle lof voor het pleidooi van Sofie Guns: er is al plasticafval genoeg op de wereld, we hebben geen exra rommel nodig.

Na de opruimactie kregen de vrijwilligers een kom soep en een broodje, en nog een bedankje. In de vorm van... Gratis plastic rommel. Ingepakt in plastic, u vriendelijk aangeboden door de Vlaamse overheid.

plastic autoboompjes

Daar zakt mijn broek dus van af.

Ik wil een oproep doen. Kreeg u ook zo'n geurboompje, en gebruikt u het niet, steek het bij mij in de brievenbus. Ik zal ze verzamelen. En dan lever ik ze terug af bij de Vlaamse overheid, dan kunnen ze ze volgend jaar opnieuw uitdelen. Want mijn kinderen leerden op school dat het altijd beter is om afval te hergebruiken.

gitlab-ci and yarn

For my previous post, on gitlab-ci and codeception, I created a small project on gitlab that runs selenium webtests during gitlab-ci. The project being tested is just a small vue.js-application.

Recently I rewrote that small application; now it uses a single file vue component. I'm not completely sure what I've done, but it seems to work, and it involves webpack encore and yarn.

Running yarn from gitlab-ci

Now the challenge was to run yarn from gitlab-ci. I was looking for a docker container with yarn (even tried to build one myself), but it took me some time before I discovered that yarn is included in the node-container.

So I now use this node container in an extra task of the build stage in my .gitlab-ci.yaml. I create an artifact with the generated javascript, which is used in the test stage. That seems to work.

As I said before, I am new to vue, and it's the first time I use yarn and webpack. So maybe I am making some obvious mistakes. Please let me know if there are things that can be done in a better way.

gitlab-ci, codeception and selenium web tests

All the php projects I work on, have tests. For some projects, we use PHPUnit as testing framework, but for more recent projects, I prefer to use Codeception, because it has an elegant way to write acceptance tests. We also use gitlab for our projects, and by adding a nifty .gitlab-ci.yml file to our source code, we made gitlab run our test suite every time new commits are pushed to the repository.

Recently, we started using Selenium WebDriver with codeception, so that we could run browser tests, to make sure that the javascripts we use keep working. Of course we wanted to run these browser tests with gitlab-ci as well, but that was not as easy as we thought it would be. The idea was to run selenium with a browser via a docker container, but the challenging part was setting up a webserver the browser could connect to.

In a first attempt, I tried to start all the containers needed for our application, running docker-compose up from the ci like we do it for local development. This worked sometimes, but after a couple of builds the docker networks used by our gitlab runners got completely messed up, which was hard to fix.

In a second attempt, I tried to use Gitlab CI Services for all the containers in our docker-compose.yml file. I gave up before I completely configured that, because I noticed the networking problems wouldn't go away.

After days of swearing, I finally got it running. I think the networking problems were caused by the nginx-container I tried to use for the web tests. But actually I didn't need a container for nginx. It turned out I could just juse the php built-in development server to run the tests.

So I ended up by adding a service for selenium with chrome and a service for mysql (the project I was trying this on, didn't really need other services), and I just added a php -S statement to the script that ran the tests, I had a running server.

I still needed a small hack, to make the browser in the selenium container actually find the webserver. I ended up using a sed-command on the configuration file of my test suite in codeception.

For reference, here is a part of my gitlab-ci.yml file:

    - LOCAL_IP=$(ip route get | awk -F"src " 'NR==1{split($2,a," ");print a[1]}')
    - echo Local IP $LOCAL_IP
    # Run the php built in server. Don't try to run nginx as a service, that only causes troubles. ;-)
    - php -S -t public/ 2> /dev/null &
    - sed -i "s/localhost:8080/$LOCAL_IP:8080/" tests/acceptance.suite.yml

Note that for this to work, I had to fiddle with the php container to have iproute2 installed.

If you want to see how it actutally works; I created a small demo project on gitlab that uses codeception in gitlab-ci to run a couple of browser tests. You can find the source code on gitlab:

Van github naar gitlab

Mijn website is een statische website. Dat wil zeggen dat de hele site automatisch wordt gegenereerd op basis van een aantal tekstbestanden. En die tekstbestanden beheer ik met git.

Gisteren verhuisde ik de git-repository met die teksten van github naar gitlab. Niet omdat ik problemen heb met het bedrijf achter github (want Microsoft is tegenwoordig érg goed bezig), maar wel omdat ik gitlab-ci wou gebruiken om mijn site te bouwen. Concreet komt het erop neer dat, telkens ik een nieuwe versie van de source push, gitlab voor mij mijn site automatisch bouwt en deployt.

Misschien heeft github ook wel zo'n service. Maar die van gitlab heb ik nu al vaak gebruikt, en ik ben er erg tevreden over. Dus vanaf nu wordt mijn blog gepowerd door nikola en gitlab. Waarvoor dank.