johnbillion / query-monitor

The developer tools panel for WordPress
https://querymonitor.com
GNU General Public License v2.0
1.59k stars 208 forks source link

Try a more reliable approach to waiting for Selenium and the database during tests #717

Closed johnbillion closed 1 year ago

johnbillion commented 1 year ago

The acceptance tests, and to a lesser degree the integration tests, are flakey during the CI runs because sometimes the Chrome container or the MariaDB container isn't ready when the tests start.

The workflows sleep for 10 seconds after starting the containers in an attempt to mitigate this, but that's not ideal and not reliable.

This PR attempts to correctly wait until the corresponding service is fully ready and healthy before running the tests

szepeviktor commented 1 year ago

docker port qm-server | grep "[0-9]+$" -ohE | head -1 These port number parsers look too futuristic. Docker must have JSON output ...

szepeviktor commented 1 year ago
docker inspect --type=container --format='{{(index .NetworkSettings.Ports "80/tcp" 0).HostPort}}' qm-server

The output is 32768 🚀

szepeviktor commented 1 year ago

There is Docker health check for you. https://docs.docker.com/compose/compose-file/#healthcheck After adding it to each container you can wait for them with a simple timeout 10 bash -c 'while [ "$(docker inspect ...)" != healthy ]; do sleep 1; done'

johnbillion commented 1 year ago

Yeah I researched healthchecks quite thoroughly, but evidently the container isn't the problem, it's the Selenium service within it. All the latest advice is not to rely on Docker-specific healthchecks and to check the service directly instead. But checking the port responsiveness seemingly isn't enough.

szepeviktor commented 1 year ago

The image author also talks about this started but not running problem. https://github.com/seleniumhq-community/docker-seleniarm#using-a-bash-script-to-wait-for-the-grid Selenium is written in Java, and a hello world in Java takes long seconds to execute.

Would you try the above shell script or the built-in /opt/bin/check-grid.sh? The previous section talks about it in their README. Basically it sends an HTTP request to Selenium.

johnbillion commented 1 year ago

Well that seems to have worked nicely, thanks. Just need to do the same thing with MariaDB now.

szepeviktor commented 1 year ago

the same thing with MariaDB

It goes like mysqladmin ping.

# Wait for MySQL
while ! mysqladmin ping 2>/dev/null; do
    echo 'Waiting for MySQL...'
    sleep 1
done

ping, ping, slee-ping :)

szepeviktor commented 1 year ago

PHP-FPM has a built-in status page. https://www.php.net/manual/en/fpm.status.php It can speak JSON. You may check whether jq -r '."process manager"' equals dynamic. ... or grep --quiet '"process manager":"dynamic"'

szepeviktor commented 1 year ago

as far as I know -u needs a space but -p does not

actually in scripts I prefer the long form for readability --user=name --password=pass

szepeviktor commented 1 year ago

Waaaait! -it means you need a terminal. Looking up docs which letter it is ... 🏃🏻‍♂️

szepeviktor commented 1 year ago

The t

  -t, --tty                  Allocate a pseudo-TTY

docker exec --help

szepeviktor commented 1 year ago

I think we should drop i too.

  -i, --interactive          Keep STDIN open even if not attached
szepeviktor commented 1 year ago

Party time 🎉 John!

johnbillion commented 1 year ago

Thanks for the pointers Viktor. I shall now retire as a programmer and never use a computer again.

johnbillion commented 1 year ago

This isn't working reliably, the integration tests are still failing quite frequently because the database connection isn't ready. Ugh.

szepeviktor commented 1 year ago
while ! curl -sSL "http://localhost:${CHROME_PORT}/wd/hub/status" 2>&1 | grep '"ready": true' >/dev/null; do

Do you think Selenium is not ready enough? Or MariaDB?