name: Playwright Tests on push on: pull_request: paths: - 'php/**' - 'Containers/mastercontainer/*.Caddyfile' - 'Containers/mastercontainer/start.sh' push: branches: - main paths: - 'php/**' - 'Containers/mastercontainer/*.Caddyfile' - 'Containers/mastercontainer/start.sh' concurrency: group: playwright-${{ github.head_ref || github.run_id }} cancel-in-progress: true env: BASE_URL: https://localhost:8080 # Master password seeded into configuration.json for the deSEC test. Seeding the config # makes AIO consider itself already installed, so /setup no longer generates/shows a # password; the seed helper writes this one and the test logs in with it directly. AIO_TEST_PASSWORD: correct horse battery staple aircraft jobs: test: timeout-minutes: 60 runs-on: ubuntu-latest steps: - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6 with: node-version: 24.15.0 - name: Install dependencies run: cd php/tests && npm ci --omit=optional - name: Install Playwright Browsers run: cd php/tests && npx playwright install --with-deps chromium - name: Set up php 8.5 uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2.37.0 with: extensions: apcu php-version: 8.5 coverage: none ini-file: development env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Adjust some things and fix permissions run: | cd php rm -r ./data rm -r ./session composer install --no-dev composer clear-cache sudo chmod 777 -R ../ - name: Start fresh development server run: | docker rm --force nextcloud-aio-{mastercontainer,apache,notify-push,nextcloud,redis,database,domaincheck,whiteboard,imaginary,talk,collabora,borgbackup} || true docker volume rm nextcloud_aio_{mastercontainer,apache,database,database_dump,nextcloud,nextcloud_data,redis,backup_cache,elasticsearch} || true docker pull ghcr.io/nextcloud-releases/all-in-one:develop docker run \ -d \ --init \ --name nextcloud-aio-mastercontainer \ --restart always \ --publish 8080:8080 \ --volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config \ --volume ./php:/var/www/docker-aio/php \ --volume ./Containers/mastercontainer/internal.Caddyfile:/internal.Caddyfile \ --volume ./Containers/mastercontainer/headers.Caddyfile:/headers.Caddyfile \ --volume ./Containers/mastercontainer/start.sh:/start.sh \ --volume /var/run/docker.sock:/var/run/docker.sock:ro \ --env SKIP_DOMAIN_VALIDATION=true \ --env APACHE_PORT=11000 \ ghcr.io/nextcloud-releases/all-in-one:develop echo Waiting for 10 seconds for the development container to start ... sleep 10 - name: Run Playwright tests for initial setup run: | cd php/tests export DEBUG=pw:api if ! npx playwright test tests/initial-setup.spec.js; then docker logs nextcloud-aio-mastercontainer docker logs nextcloud-aio-borgbackup exit 1 fi - name: Start fresh development server run: | docker rm --force nextcloud-aio-{mastercontainer,apache,notify-push,nextcloud,redis,database,domaincheck,whiteboard,imaginary,talk,collabora,borgbackup} || true docker volume rm nextcloud_aio_{mastercontainer,apache,database,database_dump,nextcloud,nextcloud_data,redis,backup_cache,elasticsearch} || true docker run \ -d \ --init \ --name nextcloud-aio-mastercontainer \ --restart always \ --publish 8080:8080 \ --volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config \ --volume ./php:/var/www/docker-aio/php \ --volume ./Containers/mastercontainer/internal.Caddyfile:/internal.Caddyfile \ --volume ./Containers/mastercontainer/headers.Caddyfile:/headers.Caddyfile \ --volume ./Containers/mastercontainer/start.sh:/start.sh \ --volume /var/run/docker.sock:/var/run/docker.sock:ro \ --env SKIP_DOMAIN_VALIDATION=false \ --env APACHE_PORT=11000 \ ghcr.io/nextcloud-releases/all-in-one:develop echo Waiting for 10 seconds for the development container to start ... sleep 10 - name: Run Playwright tests for backup restore run: | cd php/tests export DEBUG=pw:api if ! npx playwright test tests/restore-instance.spec.js; then docker logs nextcloud-aio-mastercontainer docker logs nextcloud-aio-borgbackup exit 1 fi - name: Start deSEC mock and fresh development server run: | # The deSEC flow must not touch the real deSEC API, so point it at a local mock. node php/tests/desec-mock.mjs 8090 > desec-mock.log 2>&1 & echo $! > desec-mock.pid docker rm --force nextcloud-aio-{mastercontainer,apache,notify-push,nextcloud,redis,database,domaincheck,whiteboard,imaginary,talk,collabora,borgbackup,caddy,dnsmasq} || true docker volume rm nextcloud_aio_{mastercontainer,apache,database,database_dump,nextcloud,nextcloud_data,redis,backup_cache,elasticsearch} || true # The deSEC registration entry point renders regardless of SKIP_DOMAIN_VALIDATION, # and the deSEC flow sets the domain with validation skipped internally, so no # SKIP_DOMAIN_VALIDATION override is needed here. docker run \ -d \ --init \ --name nextcloud-aio-mastercontainer \ --restart always \ --publish 8080:8080 \ --add-host host.docker.internal:host-gateway \ --volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config \ --volume ./php:/var/www/docker-aio/php \ --volume ./community-containers:/var/www/docker-aio/community-containers \ --volume ./Containers/mastercontainer/internal.Caddyfile:/internal.Caddyfile \ --volume ./Containers/mastercontainer/headers.Caddyfile:/headers.Caddyfile \ --volume ./Containers/mastercontainer/start.sh:/start.sh \ --volume /var/run/docker.sock:/var/run/docker.sock:ro \ --env APACHE_PORT=11000 \ ghcr.io/nextcloud-releases/all-in-one:develop echo Waiting for 10 seconds for the development container to start ... sleep 10 # Point the running interface at the deSEC mock via configuration.json (config-only, # no env override). The container runs PHP and has ./php mounted, so use the helper. # AIO_TEST_PASSWORD is forwarded so the helper can seed the master password too. docker exec --env AIO_TEST_PASSWORD="$AIO_TEST_PASSWORD" nextcloud-aio-mastercontainer \ php /var/www/docker-aio/php/tests/seed-desec-mock-config.php \ http://host.docker.internal:8090/api/v1 http://host.docker.internal:8090/update - name: Run Playwright tests for deSEC domain registration run: | export DEBUG=pw:api export DESEC_MOCK_URL=http://localhost:8090 # Each deSEC scenario ends by registering a domain, which persists in # configuration.json and would hide the registration UI for the next scenario. # Run each spec as its own step and re-seed (reset the deSEC state) in between. reseed() { docker exec --env AIO_TEST_PASSWORD="$AIO_TEST_PASSWORD" nextcloud-aio-mastercontainer \ php /var/www/docker-aio/php/tests/seed-desec-mock-config.php \ http://host.docker.internal:8090/api/v1 http://host.docker.internal:8090/update } dump_logs() { docker logs nextcloud-aio-mastercontainer echo "--- deSEC mock log ---" cat "$GITHUB_WORKSPACE/desec-mock.log" || true } cd php/tests if ! npx playwright test tests/desec-register.spec.js; then dump_logs; exit 1; fi reseed if ! npx playwright test tests/desec-existing.spec.js; then dump_logs; exit 1; fi kill "$(cat "$GITHUB_WORKSPACE/desec-mock.pid")" || true - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 if: ${{ !cancelled() }} with: name: playwright-report path: php/tests/playwright-report/ retention-days: 14 overwrite: true