diff --git a/Makefile b/Makefile index 27b2c30295..0a401d85d2 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,7 @@ DIST_DIRS := $(DIST)/binaries $(DIST)/release export GOEXPERIMENT ?= jsonv2 GO ?= go +CONTAINER_RUNTIME ?= docker SHASUM ?= shasum -a 256 COMMA := , @@ -468,12 +469,11 @@ migrations.individual.test\#%: .PHONY: playwright playwright: deps-frontend - @# on GitHub Actions VMs, playwright's system deps are pre-installed - @pnpm exec playwright install $(if $(GITHUB_ACTIONS),,--with-deps) chromium firefox $(PLAYWRIGHT_FLAGS) + @./tools/test-e2e.sh install .PHONY: test-e2e test-e2e: playwright frontend backend - @EXECUTABLE=$(EXECUTABLE) ./tools/test-e2e.sh $(GITEA_TEST_E2E_FLAGS) + @CONTAINER_RUNTIME=$(CONTAINER_RUNTIME) EXECUTABLE=$(EXECUTABLE) ./tools/test-e2e.sh run $(GITEA_TEST_E2E_FLAGS) .PHONY: build build: frontend backend ## build everything diff --git a/tools/test-e2e.sh b/tools/test-e2e.sh index 39405387b5..5328ddc4f1 100755 --- a/tools/test-e2e.sh +++ b/tools/test-e2e.sh @@ -1,6 +1,79 @@ #!/bin/bash set -euo pipefail +# Extract Playwright version from package.json +PLAYWRIGHT_VERSION=$(node -e "process.stdout.write(require('./package.json').devDependencies['@playwright/test'])") + +detect_playwright_mode() { + # If PLAYWRIGHT_MODE is already set to local or container, use it + if [ "${PLAYWRIGHT_MODE:-auto}" = "local" ] || [ "${PLAYWRIGHT_MODE:-auto}" = "container" ]; then + return + fi + + # Default to local + PLAYWRIGHT_MODE="local" + + if [ "$(uname -s)" = "Linux" ]; then + if [ -f /etc/os-release ]; then + # Check ID and ID_LIKE for ubuntu or debian + if ! grep -qE '^ID(_LIKE)?=.*(ubuntu|debian)' /etc/os-release; then + PLAYWRIGHT_MODE="container" + fi + else + PLAYWRIGHT_MODE="container" + fi + fi +} + +wait_for_container() { + local max_attempts=$1 + local attempt=1 + local wait_time=1 + echo "Waiting for container to start..." + sleep 5 # give the container some time to start listening. + + while [ $attempt -le $max_attempts ]; do + if ${CONTAINER_RUNTIME:-docker} logs gitea-e2e-runner 2>&1 | grep -q "Listening on"; then + echo "Container is ready." + return 0 # Success + fi + + if [ $attempt -eq $max_attempts ]; then + echo "Error: Container did not become ready after $max_attempts attempts." + return 1 # Failure + fi + + echo "Attempt $attempt: Container not ready, waiting $wait_time second(s)..." + sleep $wait_time + ((attempt++)) + ((wait_time*=2)) # Exponential backoff + done +} + +CMD="${1:-run}" +if [ "$CMD" = "install" ] || [ "$CMD" = "run" ]; then + shift +else + CMD="run" +fi + +detect_playwright_mode + +if [ "$CMD" = "install" ]; then + if [ "$PLAYWRIGHT_MODE" = "local" ]; then + # on Github Actions VMs, playwright's system deps are preinstalled + if [ -z "${GITHUB_ACTIONS:-}" ]; then + pnpm exec playwright install --with-deps chromium firefox ${PLAYWRIGHT_FLAGS:-} + else + pnpm exec playwright install chromium firefox ${PLAYWRIGHT_FLAGS:-} + fi + else + echo "Running playwright in container as host distro is not supported by playwright directly" + ${CONTAINER_RUNTIME:-docker} pull "mcr.microsoft.com/playwright:v${PLAYWRIGHT_VERSION}-noble" + fi + exit 0 +fi + # Create isolated work directory WORK_DIR=$(mktemp -d) @@ -8,6 +81,9 @@ WORK_DIR=$(mktemp -d) FREE_PORT=$(node -e "const s=require('net').createServer();s.listen(0,'127.0.0.1',()=>{process.stdout.write(String(s.address().port));s.close()})") cleanup() { + if [ "${PLAYWRIGHT_MODE:-}" = "container" ]; then + ${CONTAINER_RUNTIME:-docker} stop gitea-e2e-runner + fi if [ -n "${SERVER_PID:-}" ]; then kill "$SERVER_PID" 2>/dev/null || true wait "$SERVER_PID" 2>/dev/null || true @@ -16,6 +92,16 @@ cleanup() { } trap cleanup EXIT +if [ "${PLAYWRIGHT_MODE:-}" = "container" ]; then + # Start playwright worker + ${CONTAINER_RUNTIME:-docker} run --network=host --name gitea-e2e-runner -d --rm --init -it --workdir /home/pwuser --user pwuser "mcr.microsoft.com/playwright:v${PLAYWRIGHT_VERSION}-noble" /bin/sh -c "npx -y playwright@${PLAYWRIGHT_VERSION} run-server --port 4000 --host 0.0.0.0" + + if ! wait_for_container 5; then + exit 1 + fi +fi + + # Write config file for isolated instance mkdir -p "$WORK_DIR/custom/conf" cat > "$WORK_DIR/custom/conf/app.ini" <