test(e2e): make root docker-compose stack port-configurable
Some checks failed
ci / tests (push) Has been cancelled

Parameterize Matomo’s published port via MATOMO_PORT to avoid CI collisions,
update installer site URL accordingly, and adapt the root docker-compose E2E
test to run on a non-default port with explicit environment injection.

https://chatgpt.com/share/694af650-a484-800f-ace7-0a634d57b0a0
This commit is contained in:
Kevin Veen-Birkenbach
2025-12-23 21:16:51 +01:00
parent 7fa8b580d2
commit 1f448f4457
2 changed files with 39 additions and 11 deletions

View File

@@ -24,7 +24,7 @@ services:
db: db:
condition: service_healthy condition: service_healthy
ports: ports:
- "8080:80" - "${MATOMO_PORT:-8080}:80"
environment: environment:
MATOMO_DATABASE_HOST: db MATOMO_DATABASE_HOST: db
MATOMO_DATABASE_ADAPTER: mysql MATOMO_DATABASE_ADAPTER: mysql
@@ -57,7 +57,7 @@ services:
# Installer flow values # Installer flow values
MATOMO_SITE_NAME: "Matomo (docker-compose)" MATOMO_SITE_NAME: "Matomo (docker-compose)"
MATOMO_SITE_URL: "http://127.0.0.1:8080" MATOMO_SITE_URL: "http://127.0.0.1:${MATOMO_PORT:-8080}"
MATOMO_TIMEZONE: "Germany - Berlin" MATOMO_TIMEZONE: "Germany - Berlin"
# Optional stability knobs # Optional stability knobs

View File

@@ -1,6 +1,5 @@
import json import json
import os import os
import re
import subprocess import subprocess
import time import time
import unittest import unittest
@@ -8,16 +7,25 @@ import urllib.request
COMPOSE_FILE = os.environ.get("MATOMO_STACK_COMPOSE_FILE", "docker-compose.yml") COMPOSE_FILE = os.environ.get("MATOMO_STACK_COMPOSE_FILE", "docker-compose.yml")
MATOMO_HOST_URL = os.environ.get("MATOMO_STACK_URL", "http://127.0.0.1:8080")
# Pick a non-default port to avoid collisions with other CI stacks that use 8080
MATOMO_PORT = os.environ.get("MATOMO_PORT", "18080")
MATOMO_HOST_URL = os.environ.get("MATOMO_STACK_URL", f"http://127.0.0.1:{MATOMO_PORT}")
# How long we wait for Matomo HTTP to respond at all (seconds) # How long we wait for Matomo HTTP to respond at all (seconds)
WAIT_TIMEOUT_SECONDS = int(os.environ.get("MATOMO_STACK_WAIT_TIMEOUT", "180")) WAIT_TIMEOUT_SECONDS = int(os.environ.get("MATOMO_STACK_WAIT_TIMEOUT", "180"))
def _run(cmd: list[str], *, check: bool = True) -> subprocess.CompletedProcess: def _run(
cmd: list[str],
*,
check: bool = True,
extra_env: dict[str, str] | None = None,
) -> subprocess.CompletedProcess:
return subprocess.run( return subprocess.run(
cmd, cmd,
check=check, check=check,
env={**os.environ, **(extra_env or {})},
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, stderr=subprocess.PIPE,
text=True, text=True,
@@ -55,7 +63,7 @@ class TestRootDockerComposeStack(unittest.TestCase):
1) docker compose down -v 1) docker compose down -v
2) docker compose build bootstrap 2) docker compose build bootstrap
3) docker compose up -d db matomo 3) docker compose up -d db matomo
4) wait for Matomo HTTP on host port (default 8080) 4) wait for Matomo HTTP on host port (default 8080, overridden here)
5) docker compose run --rm bootstrap -> token on stdout 5) docker compose run --rm bootstrap -> token on stdout
6) validate token via Matomo API call 6) validate token via Matomo API call
7) docker compose down -v (cleanup) 7) docker compose down -v (cleanup)
@@ -63,26 +71,46 @@ class TestRootDockerComposeStack(unittest.TestCase):
def setUp(self) -> None: def setUp(self) -> None:
# Always start from a clean slate (also clears volumes) # Always start from a clean slate (also clears volumes)
_run(_compose_cmd("down", "-v"), check=False) _run(
_compose_cmd("down", "-v"),
check=False,
extra_env={"MATOMO_PORT": MATOMO_PORT},
)
def tearDown(self) -> None: def tearDown(self) -> None:
# Cleanup even if assertions fail # Cleanup even if assertions fail
_run(_compose_cmd("down", "-v"), check=False) _run(
_compose_cmd("down", "-v"),
check=False,
extra_env={"MATOMO_PORT": MATOMO_PORT},
)
def test_root_docker_compose_yml_stack_bootstraps_and_token_works(self) -> None: def test_root_docker_compose_yml_stack_bootstraps_and_token_works(self) -> None:
# Build bootstrap image from Dockerfile (as defined in docker-compose.yml) # Build bootstrap image from Dockerfile (as defined in docker-compose.yml)
build = _run(_compose_cmd("build", "bootstrap"), check=True) build = _run(
_compose_cmd("build", "bootstrap"),
check=True,
extra_env={"MATOMO_PORT": MATOMO_PORT},
)
self.assertEqual(build.returncode, 0, build.stderr) self.assertEqual(build.returncode, 0, build.stderr)
# Start db + matomo (bootstrap is one-shot and started via "run") # Start db + matomo (bootstrap is one-shot and started via "run")
up = _run(_compose_cmd("up", "-d", "db", "matomo"), check=True) up = _run(
_compose_cmd("up", "-d", "db", "matomo"),
check=True,
extra_env={"MATOMO_PORT": MATOMO_PORT},
)
self.assertEqual(up.returncode, 0, up.stderr) self.assertEqual(up.returncode, 0, up.stderr)
# Wait until Matomo answers on the published port # Wait until Matomo answers on the published port
_wait_for_http_any_status(MATOMO_HOST_URL + "/", WAIT_TIMEOUT_SECONDS) _wait_for_http_any_status(MATOMO_HOST_URL + "/", WAIT_TIMEOUT_SECONDS)
# Run bootstrap: it should print ONLY the token to stdout # Run bootstrap: it should print ONLY the token to stdout
boot = _run(_compose_cmd("run", "--rm", "bootstrap"), check=True) boot = _run(
_compose_cmd("run", "--rm", "bootstrap"),
check=True,
extra_env={"MATOMO_PORT": MATOMO_PORT},
)
token = (boot.stdout or "").strip() token = (boot.stdout or "").strip()
self.assertRegex( self.assertRegex(