Ga door naar de hoofdinhoud

Updating your Symfony app from Mercure 0.10 to Mercure 0.11

Last wednesday I updated dikdikdik, a score sheet app for solo whist, so that it now uses Mercure v0.11, instead of v0.10. I use docker-compose for the development environment of dikdikdik, and GitLab CI/CD to run the end-to-end tests with codeception and selenium.

Mercure v0.11

This was not a trivial update, because v0.11 was a major milestone for the Mercure project. In retrospect, I didn't have to change much, but it took me some time to find out what exactly I had to change, especially to make the end-to-end tests running again.

Lees verder…

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

Lees verder…

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

Lees verder…

Wiezen in quarantaine met WDEBELEK

Nu het aantal dagelijkse nieuwe COVID-19-besmettingen een aantal dagen op rij toeneemt, en er in de media al gesproken wordt over mogelijke plaatselijke lockdowns, vergroot ook de kans op kaartavonden die geannuleerd worden wegens coronagevaar.

Maar in tegenstelling tot de vorige lockdown, is er nu wel een makkelijke oplossing om te wiezen vanuit uw kot (en hiermee bedoel ik dan traditioneel wiezen, want voor kleurenwiezen bestonden er al langer oplossingen). Want ik werk aan een webtoepassing om online te kaarten: WDEBELEK, in de volksmond ook wel eens ‘de wiezen-app’. (En als ik dat zo vermeld, wordt ze misschien makkelijker gevonden door Google en consoorten ;-))

De toepassing staat nog in zijn kinderschoenen, en er zijn nog heel wat losse eindjes, maar ze is wel al uitgebreid getest, en bruikbaar gebleken. Hoe gaat het in z'n werk:

  1. Vind 3 tot 5 vrienden die samen met jou willen wiezen.
  2. Start een video-conference met die vrienden; gebruik je favoriete video-conferencing tool. (Bijv. praatbox.be, maar uiteraard is eender welke tool geschikt.)
  3. Maak een kaarttafel aan op kaart.rijkvanafdronk.be.
  4. Maak uitnodigingen voor je vrienden, en bezorg hen de links.
  5. Kaarten maar!

Het is aangewezen om er de handleiding een keertje op na te slaan, maar in principe zou het allemaal vrij intuitief moeten zijn.

De broncode van de toepassing is vrij beschikbaar onder de voorwaarden van de AGPL v3 of later. En je kunt ze gratis gebruiken. Dat is: zo lang mijn server dat kan trekken, uiteraard.

Veel kaartplezier!

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:

variables:
  JWT_KEY: YourSecretKey
  DEMO: 1
  ALLOW_ANONYMOUS: 1
  HEARTBEAT_INTERVAL: 30s
  ADDR: ':3000'
  CORS_ALLOWED_ORIGINS: '*'
  PUBLISH_ALLOWED_ORIGINS: '*'

# ...

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.
  image: registry.gitlab.com/rva-vzw/dikdikdik.php
  services:
    - 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.

MERCURE_PUBLISH_URL=http://mercure:3000/.well-known/mercure
MERCURE_JWT_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InB1Ymxpc2giOltdfX0.FFSjymJCGRDWrmAmPJDoVGuYwnx5FRTjRFkkYfvLkUg

(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:

  script:
    - 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]
 [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: een score app voor het wiezen

Ik werk al een tijdje aan een webtoepassing die ons helpt bij het noteren van de scores bij het wiezen. Als hobbyproject. En gisteren bereikte deze score-app (met de welluidende naam 'dikdikdik') versie 1.0. Dus een aankondiging is hier wel op zijn plaats, dacht ik zo.

Wat betreft user interface, is er nog wel wat ruimte voor verbetering. Maar het is een coole toepassing, vind ik zelf toch, met een fijne event-sourced backend, en gitlab pipelines die nieuwe broncode automatisch testen. 🤓

De score-app hanteert de spelregels van het wiezen zoals die vastgelegd zijn door Rijk van Afdronk vzw. Een demo-versie van de toepassing is tot nader order beschikbaar op score.rijkvanafdronk.be.

ik kan hem maar één keer halen

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 8.8.8.8 | 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 0.0.0.0:8080 -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: https://gitlab.com/johanv/codeception-ci-demo.