Testing: JS tests need playwright #299
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: EGroupware Testing | |
| on: | |
| pull_request: | |
| push: | |
| branches: | |
| - master | |
| workflow_dispatch: | |
| jobs: | |
| phpunit: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 45 | |
| env: | |
| EGW_DB_ROOT_PW: ciroot | |
| COMPOSE_PROJECT_NAME: egwci | |
| EGW_CI_ROOT: ${{ github.workspace }}/sources | |
| EGW_CI_DOCKER_DIR: ${{ github.workspace }}/sources/doc/docker | |
| EGW_SRC_DIR: /var/www | |
| EGW_CONFIG_USER: "" | |
| EGW_CONFIG_PASSWD: "" | |
| SYSOP_USER: "" | |
| SYSOP_PASS: "" | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| submodules: true | |
| path: sources | |
| - name: Cache Composer downloads | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.composer/cache | |
| key: composer-cache-${{ runner.os }}-${{ hashFiles('sources/composer.lock') }} | |
| restore-keys: | | |
| composer-cache-${{ runner.os }}- | |
| - name: Install PHP dependencies in sources | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| COMPOSER_CACHE_DIR="${HOME}/.composer/cache" | |
| docker run --rm --user "$(id -u):$(id -g)" \ | |
| -v "${COMPOSER_CACHE_DIR}":/tmp/composer-cache \ | |
| -v "${GITHUB_WORKSPACE}/sources":/app -w /app \ | |
| -e COMPOSER_CACHE_DIR=/tmp/composer-cache \ | |
| composer install --no-interaction --ignore-platform-reqs | |
| php "${GITHUB_WORKSPACE}/sources/install-cli.php" --git-apps pull | |
| - name: Prepare compose project layout | |
| run: | | |
| set -euo pipefail | |
| mkdir -p "$GITHUB_WORKSPACE/sources/doc/docker/data" "$GITHUB_WORKSPACE/sources/doc/docker/sessions" | |
| rm -f "$GITHUB_WORKSPACE/sources/doc/docker/data/header.inc.php" | |
| - name: Start CI containers | |
| run: | | |
| set -euo pipefail | |
| COMPOSE="docker compose --project-directory $GITHUB_WORKSPACE/sources \ | |
| -f $GITHUB_WORKSPACE/sources/doc/docker/docker-compose.yml \ | |
| -f $GITHUB_WORKSPACE/sources/doc/docker/docker-compose.ci.yml" | |
| $COMPOSE up -d --force-recreate db egroupware nginx | |
| - name: Install PHP extensions | |
| run: | | |
| set -euo pipefail | |
| COMPOSE="docker compose --project-directory $GITHUB_WORKSPACE/sources \ | |
| -f $GITHUB_WORKSPACE/sources/doc/docker/docker-compose.yml \ | |
| -f $GITHUB_WORKSPACE/sources/doc/docker/docker-compose.ci.yml" | |
| $COMPOSE exec -T egroupware sh -lc ' | |
| set -e | |
| php_version="$(php -r "echo PHP_MAJOR_VERSION . \".\" . PHP_MINOR_VERSION;")" | |
| apt-get update | |
| if ! apt-get install -y "php${php_version}-tidy"; then | |
| apt-get install -y php-tidy | |
| fi | |
| php -m | grep -i tidy | |
| ' | |
| - name: Wait for install | |
| run: | | |
| set -euo pipefail | |
| COMPOSE="docker compose --project-directory $GITHUB_WORKSPACE/sources \ | |
| -f $GITHUB_WORKSPACE/sources/doc/docker/docker-compose.yml \ | |
| -f $GITHUB_WORKSPACE/sources/doc/docker/docker-compose.ci.yml" | |
| MAX_WAIT=60 | |
| WAIT_INTERVAL=5 | |
| ELAPSED=0 | |
| SUCCESS_MSG="EGroupware successful installed" | |
| echo "Waiting for database to be ready..." | |
| until $COMPOSE exec -T db mariadb-admin ping -h "db" --silent --user=root --password="$EGW_DB_ROOT_PW"; do | |
| if [ "$ELAPSED" -ge "$MAX_WAIT" ]; then | |
| echo "::error::Timed out waiting for EGroupware installation" | |
| echo "==== egroupware logs ====" | |
| $COMPOSE logs egroupware || true | |
| echo "==== database logs ====" | |
| $COMPOSE logs db || true | |
| exit 1 | |
| fi | |
| echo " ... waiting for DB" | |
| sleep "$WAIT_INTERVAL" | |
| ELAPSED=$((ELAPSED + WAIT_INTERVAL)) | |
| done | |
| echo "Waiting for EGroupware installation log message..." | |
| until $COMPOSE logs egroupware | grep -q "$SUCCESS_MSG"; do | |
| if [ "$ELAPSED" -ge "$MAX_WAIT" ]; then | |
| echo "::error::Timed out waiting for EGroupware installation" | |
| echo "==== egroupware logs ====" | |
| $COMPOSE logs egroupware || true | |
| echo "==== database logs ====" | |
| $COMPOSE logs db || true | |
| exit 1 | |
| fi | |
| sleep "$WAIT_INTERVAL" | |
| ELAPSED=$((ELAPSED + WAIT_INTERVAL)) | |
| echo " ... still waiting (${ELAPSED}s)" | |
| done | |
| $COMPOSE exec -T egroupware ln -sf /var/lib/egroupware/header.inc.php "$EGW_SRC_DIR/header.inc.php" | |
| - name: Extract install credentials | |
| run: | | |
| set -euo pipefail | |
| COMPOSE="docker compose --project-directory $GITHUB_WORKSPACE/sources \ | |
| -f $GITHUB_WORKSPACE/sources/doc/docker/docker-compose.yml \ | |
| -f $GITHUB_WORKSPACE/sources/doc/docker/docker-compose.ci.yml" | |
| # Get sysop admin user from install log | |
| SYSOP_USER="sysop" | |
| SYSOP_PASS="$( | |
| $COMPOSE logs egroupware | | |
| awk ' | |
| /EGroupware username: sysop/ {found=1; next} | |
| found && /password:/ { | |
| sub(/^[^:]*:[[:space:]]*/, "", $0) | |
| exit | |
| } | |
| ' | |
| )" | |
| # Get setup user/password from install log. | |
| CONFIG_USER="$( | |
| $COMPOSE logs egroupware | | |
| awk ' | |
| /Setup username:/ {sub(/.*Setup username:[[:space:]]*/, "", $0); print; exit} | |
| ' | |
| )" | |
| CONFIG_PASS="$( | |
| $COMPOSE logs egroupware | | |
| awk ' | |
| /Setup username:/ {found=1; next} | |
| found && /password:/ { | |
| sub(/^[^:]*:[[:space:]]*/, "", $0) | |
| exit | |
| } | |
| ' | |
| )" | |
| for v in SYSOP_USER SYSOP_PASS CONFIG_USER CONFIG_PASS; do | |
| if [ -z "${!v}" ]; then | |
| echo "::error::Missing $v" | |
| exit 1 | |
| fi | |
| done | |
| { | |
| echo "SYSOP_USER=$SYSOP_USER" | |
| echo "SYSOP_PASS=$SYSOP_PASS" | |
| echo "EGW_CONFIG_USER=$CONFIG_USER" | |
| echo "EGW_CONFIG_PASSWD=$CONFIG_PASS" | |
| } >> "$GITHUB_ENV" | |
| - name: Debug admin-cli path mapping | |
| run: | | |
| set -euo pipefail | |
| COMPOSE="docker compose --project-directory $GITHUB_WORKSPACE/sources \ | |
| -f $GITHUB_WORKSPACE/sources/doc/docker/docker-compose.yml \ | |
| -f $GITHUB_WORKSPACE/sources/doc/docker/docker-compose.ci.yml" | |
| echo "== Host checks ==" | |
| pwd | |
| ls -la "$GITHUB_WORKSPACE/sources/admin/admin-cli.php" || true | |
| ls -la "$GITHUB_WORKSPACE/sources/admin" | sed -n '1,80p' || true | |
| echo "== Compose resolved mounts (egroupware service) ==" | |
| docker compose --project-directory "$GITHUB_WORKSPACE/sources" \ | |
| -f "$GITHUB_WORKSPACE/sources/doc/docker/docker-compose.yml" \ | |
| -f "$GITHUB_WORKSPACE/sources/doc/docker/docker-compose.ci.yml" \ | |
| config | sed -n '/egroupware:/,/db:/p' | |
| echo "== Container checks ==" | |
| $COMPOSE exec -T egroupware sh -lc 'pwd; ls -la /var/www | sed -n "1,80p"; ls -la /var/www/admin | sed -n "1,80p" || true; ls -la /var/www/egroupware/admin | sed -n "1,80p" || true' | |
| $COMPOSE exec -T egroupware sh -lc 'test -f /var/www/admin/admin-cli.php && echo "admin-cli in /var/www" || true; test -f /var/www/egroupware/admin/admin-cli.php && echo "admin-cli in /var/www/egroupware" || true' | |
| - name: Detect app root in container | |
| run: | | |
| set -euo pipefail | |
| COMPOSE="docker compose --project-directory $GITHUB_WORKSPACE/sources \ | |
| -f $GITHUB_WORKSPACE/sources/doc/docker/docker-compose.yml \ | |
| -f $GITHUB_WORKSPACE/sources/doc/docker/docker-compose.ci.yml" | |
| APP_DIR="$( | |
| $COMPOSE exec -T egroupware sh -lc ' | |
| if [ -f /var/www/admin/admin-cli.php ]; then | |
| echo /var/www | |
| elif [ -f /var/www/egroupware/admin/admin-cli.php ]; then | |
| echo /var/www/egroupware | |
| else | |
| exit 1 | |
| fi | |
| ' | |
| )" | |
| echo "EGW_SRC_DIR=$APP_DIR" >> "$GITHUB_ENV" | |
| echo "Detected EGW_SRC_DIR=$APP_DIR" | |
| - name: Configure for phpunit test (apps, user) | |
| run: | | |
| set -euo pipefail | |
| COMPOSE="docker compose --project-directory $GITHUB_WORKSPACE/sources \ | |
| -f $GITHUB_WORKSPACE/sources/doc/docker/docker-compose.yml \ | |
| -f $GITHUB_WORKSPACE/sources/doc/docker/docker-compose.ci.yml" | |
| # Get test user from phpunit.xml | |
| EGW_TEST_USER="$( | |
| sed -n 's/.*<var name="EGW_USER" value="\([^"]*\)".*/\1/p' "$GITHUB_WORKSPACE/sources/doc/phpunit.xml" | |
| )" | |
| EGW_TEST_PASS="$( | |
| sed -n 's/.*<var name="EGW_PASSWORD" value="\([^"]*\)".*/\1/p' "$GITHUB_WORKSPACE/sources/doc/phpunit.xml" | |
| )" | |
| for v in SYSOP_USER SYSOP_PASS EGW_TEST_USER EGW_TEST_PASS; do | |
| if [ -z "${!v}" ]; then | |
| echo "::error::Missing $v" | |
| exit 1 | |
| fi | |
| done | |
| { | |
| echo "SYSOP_USER=$SYSOP_USER" | |
| echo "SYSOP_PASS=$SYSOP_PASS" | |
| } >> "$GITHUB_ENV" | |
| $COMPOSE exec -T -w "$EGW_SRC_DIR" egroupware php admin/admin-cli.php \ | |
| --edit-user "$SYSOP_USER,$SYSOP_PASS,$EGW_TEST_USER,Test,User,$EGW_TEST_PASS,$EGW_TEST_USER@example.invalid" | |
| # Ensure share links resolve locally in CI | |
| $COMPOSE exec -T -w "$EGW_SRC_DIR" egroupware php setup/setup-cli.php \ | |
| --config default,"$EGW_CONFIG_USER","$EGW_CONFIG_PASSWD",hostname=localhost,webserver_url=/egroupware | |
| - name: Debug web access | |
| run: | | |
| set -euo pipefail | |
| COMPOSE="docker compose --project-directory $GITHUB_WORKSPACE/sources \ | |
| -f $GITHUB_WORKSPACE/sources/doc/docker/docker-compose.yml \ | |
| -f $GITHUB_WORKSPACE/sources/doc/docker/docker-compose.ci.yml" | |
| docker compose exec nginx nginx -T || true | |
| docker compose exec nginx ss -lntp || true | |
| $COMPOSE exec -T egroupware sh -lc ' | |
| which curl || apt-get update && apt-get install -y curl | |
| echo "Testing 'nginx' URL:" | |
| curl -I -v http://nginx/ || true | |
| echo | |
| echo "Listening ports:" | |
| ss -lntp || netstat -lntp || true | |
| ' | |
| - name: Install fixture test app | |
| run: | | |
| set -euo pipefail | |
| COMPOSE="docker compose --project-directory $GITHUB_WORKSPACE/sources \ | |
| -f $GITHUB_WORKSPACE/sources/doc/docker/docker-compose.yml \ | |
| -f $GITHUB_WORKSPACE/sources/doc/docker/docker-compose.ci.yml" | |
| # Ensure fixture test app is linked and installed before tests | |
| $COMPOSE exec -T \ | |
| -e EGW_CONFIG_USER="$EGW_CONFIG_USER" \ | |
| -e EGW_CONFIG_PASSWD="$EGW_CONFIG_PASSWD" \ | |
| -w "$EGW_SRC_DIR" egroupware sh -lc ' | |
| if [ -d api/tests/fixtures/apps/test ]; then | |
| ln -sfn api/tests/fixtures/apps/test test | |
| set +e | |
| php setup/setup-cli.php --update default,$EGW_CONFIG_USER,$EGW_CONFIG_PASSWD,no,test | |
| rc=$? | |
| set -e | |
| echo "setup-cli exit code: $rc" | |
| fi | |
| ' | |
| if ! $COMPOSE exec -T db mariadb -u root -p"$EGW_DB_ROOT_PW" -D "egroupware" -e "SHOW TABLES LIKE 'egw_test%';" | grep -q "egw_test"; then | |
| echo "egw_test table not found after test app install, some tests will be skipped" | |
| fi | |
| - name: Disable swoolepush for CI tests | |
| run: | | |
| set -euo pipefail | |
| COMPOSE="docker compose --project-directory $GITHUB_WORKSPACE/sources \ | |
| -f $GITHUB_WORKSPACE/sources/doc/docker/docker-compose.yml \ | |
| -f $GITHUB_WORKSPACE/sources/doc/docker/docker-compose.ci.yml" | |
| $COMPOSE exec -T db mariadb -u root -p"$EGW_DB_ROOT_PW" -D "egroupware" -e \ | |
| "UPDATE egw_applications SET app_enabled=-1 WHERE app_name='swoolepush';" | |
| $COMPOSE exec -T -w "$EGW_SRC_DIR" egroupware php -r ' | |
| require "api/src/loader/common.php"; | |
| \EGroupware\Api\Cache::unsetInstance(\EGroupware\Api\Egw\Applications::class, "apps"); | |
| \EGroupware\Api\Cache::unsetInstance(\EGroupware\Api\Hooks::class, "locations"); | |
| ' | |
| - name: Run PHPUnit | |
| timeout-minutes: 30 | |
| run: | | |
| set -euo pipefail | |
| COMPOSE="docker compose --project-directory $GITHUB_WORKSPACE/sources \ | |
| -f $GITHUB_WORKSPACE/sources/doc/docker/docker-compose.yml \ | |
| -f $GITHUB_WORKSPACE/sources/doc/docker/docker-compose.ci.yml" | |
| EGW_CONFIG_USER="${EGW_CONFIG_USER:-}" | |
| EGW_CONFIG_PASSWD="${EGW_CONFIG_PASSWD:-}" | |
| for v in EGW_CONFIG_USER EGW_CONFIG_PASSWD; do | |
| if [ -z "${!v}" ]; then | |
| echo "::error::Missing $v" | |
| exit 1 | |
| fi | |
| done | |
| # Run tests with local HTTP endpoint inside egroupware container | |
| $COMPOSE exec -T \ | |
| -e HTTP_HOST=127.0.0.1:8081 \ | |
| -e HTTP_X_FORWARDED_PROTO=http \ | |
| -e EGW_URL=http://127.0.0.1:8081 \ | |
| -e EGW_CONFIG_USER="$EGW_CONFIG_USER" \ | |
| -e EGW_CONFIG_PASSWD="$EGW_CONFIG_PASSWD" \ | |
| -w "$EGW_SRC_DIR" egroupware \ | |
| bash -lc ' | |
| set -euo pipefail | |
| php -S 127.0.0.1:8081 -t "$PWD" > /tmp/egw-phpunit-http.log 2>&1 & | |
| server_pid=$! | |
| trap "kill $server_pid 2>/dev/null || true" EXIT | |
| for i in $(seq 1 20); do | |
| php -r '\''$fp=@fsockopen("127.0.0.1",8081,$errno,$errstr,0.2); if($fp){fclose($fp); exit(0);} exit(1);'\'' && break | |
| sleep 1 | |
| done | |
| php vendor/bin/phpunit --configuration doc/phpunit.xml | |
| ' | |
| - name: Tear down | |
| if: always() | |
| run: | | |
| COMPOSE="docker compose --project-directory $GITHUB_WORKSPACE/sources \ | |
| -f $GITHUB_WORKSPACE/sources/doc/docker/docker-compose.yml \ | |
| -f $GITHUB_WORKSPACE/sources/doc/docker/docker-compose.ci.yml" | |
| $COMPOSE down -v --remove-orphans | |
| jstest: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| submodules: true | |
| - name: Setup Node | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version-file: package.json | |
| - name: Install npm dependencies | |
| run: npm ci | |
| - name: Install Playwright browsers | |
| run: npx playwright install --with-deps chromium firefox | |
| - name: Run jstest | |
| run: npm run jstest |