name: E2E on: push: branches: [ main, next ] merge_group: pull_request: env: TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} TURBO_TEAM: ${{ vars.TURBO_TEAM || github.repository_owner }} BETTER_AUTH_TELEMETRY_ENDPOINT: ${{ vars.BETTER_AUTH_TELEMETRY_ENDPOINT }} permissions: {} concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.event.merge_group.head_ref || github.ref }} cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: smoke: name: Smoke test (${{ matrix.node-version }}) timeout-minutes: 30 runs-on: ${{ (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == 'better-auth/better-auth' || github.event_name != 'pull_request' && github.repository == 'better-auth/better-auth') && 'starsling-ubuntu-24.04' || 'ubuntu-24.04' }} strategy: fail-fast: false matrix: node-version: [22.x, 24.x] permissions: contents: read env: COMPOSE_SERVICES: redis steps: - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: fetch-depth: 0 persist-credentials: false - name: Cache turbo build setup uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: .turbo key: ${{ runner.os }}-turbo-${{ github.sha }} restore-keys: | ${{ runner.os }}-turbo- - uses: better-auth/shared-workflows/.github/actions/setup-pnpm@08e5520e7a829b03bee1152913682b67d2ba44b1 with: node-version: ${{ matrix.node-version }} - name: Build run: pnpm build - name: Reset Docker Containers run: docker compose down --volumes --remove-orphans - name: Start Docker Containers run: | read -r -a compose_services <<< "$COMPOSE_SERVICES" docker compose up -d --wait --wait-timeout 60 "${compose_services[@]}" - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 - uses: denoland/setup-deno@667a34cdef165d8d2b2e98dde39547c9daac7282 # v2.0.4 with: deno-version: 2.6.4 - name: Smoke timeout-minutes: 10 run: pnpm e2e:smoke - name: Docker Compose Diagnostics if: failure() && hashFiles('docker-compose.yml') != '' run: | read -r -a compose_services <<< "$COMPOSE_SERVICES" docker compose ps --all || true docker compose logs --no-color "${compose_services[@]}" || true - name: Stop Docker Containers if: always() && hashFiles('docker-compose.yml') != '' run: docker compose down --volumes --remove-orphans integration: name: Integration test timeout-minutes: 60 runs-on: ${{ (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == 'better-auth/better-auth' || github.event_name != 'pull_request' && github.repository == 'better-auth/better-auth') && 'starsling-ubuntu-24.04' || 'ubuntu-24.04' }} permissions: contents: read env: COMPOSE_SERVICES: postgres steps: - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: fetch-depth: 0 persist-credentials: false - name: Cache turbo build setup uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: .turbo key: ${{ runner.os }}-turbo-${{ github.sha }} restore-keys: | ${{ runner.os }}-turbo- - uses: better-auth/shared-workflows/.github/actions/setup-pnpm@08e5520e7a829b03bee1152913682b67d2ba44b1 - name: Install Next.js demo run: pnpm --dir demo/nextjs install --frozen-lockfile - name: Install Playwright Browsers uses: ./.github/actions/setup-playwright - name: Reset Docker Containers run: docker compose down --volumes --remove-orphans - name: Start Docker Containers run: | read -r -a compose_services <<< "$COMPOSE_SERVICES" docker compose up -d --wait --wait-timeout 60 "${compose_services[@]}" - name: Integration run: pnpm e2e:integration --filter=./e2e/integration - name: Build Next.js demo working-directory: demo/nextjs env: BETTER_AUTH_SECRET: better-auth-scim-demo-ci-secret-at-least-thirty-two-characters BETTER_AUTH_URL: http://127.0.0.1:3000 DEMO_SQLITE_PATH: ${{ runner.temp }}/better-auth-scim-demo-build.sqlite SCIM_DEMO_ENABLED: "true" SCIM_DEMO_OIDC_CLIENT_SECRET: better-auth-scim-demo-ci-oidc-client-secret SCIM_DEMO_TOKEN: better-auth-scim-demo-ci-token run: pnpm build - name: Upload integration browser artifacts if: always() uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: integration-playwright-artifacts path: | e2e/integration/playwright-report e2e/integration/test-results if-no-files-found: ignore retention-days: 7 - name: Docker Compose Diagnostics if: failure() && hashFiles('docker-compose.yml') != '' run: | read -r -a compose_services <<< "$COMPOSE_SERVICES" docker compose ps --all || true docker compose logs --no-color "${compose_services[@]}" || true - name: Stop Docker Containers if: always() && hashFiles('docker-compose.yml') != '' run: docker compose down --volumes --remove-orphans adapter-integration: name: ${{ matrix.packages }} Integration Test runs-on: ${{ (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == 'better-auth/better-auth' || github.event_name != 'pull_request' && github.repository == 'better-auth/better-auth') && 'starsling-ubuntu-24.04' || 'ubuntu-24.04' }} timeout-minutes: 30 permissions: contents: read strategy: fail-fast: false matrix: include: - packages: "@better-auth-test/adapter-factory" compose_services: "" - packages: "@better-auth-test/drizzle-adapter" compose_services: "postgres mysql" - packages: "@better-auth-test/drizzle-v2-relations-adapter" compose_services: "postgres mysql" - packages: "@better-auth-test/kysely-prisma-adapter" compose_services: "postgres-kysely mysql-kysely postgres-kysely2 mssql" - packages: "@better-auth-test/memory-adapter" compose_services: "" - packages: "@better-auth-test/mongo-adapter" compose_services: "mongodb" - packages: "@better-auth-test/prisma-adapter" compose_services: "postgres-prisma mysql-prisma" env: COMPOSE_SERVICES: ${{ matrix.compose_services }} FILTER: ${{ matrix.packages }} steps: - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: fetch-depth: 0 persist-credentials: false - name: Cache turbo build setup uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: .turbo key: ${{ runner.os }}-turbo-${{ github.sha }} restore-keys: | ${{ runner.os }}-turbo- - uses: better-auth/shared-workflows/.github/actions/setup-pnpm@08e5520e7a829b03bee1152913682b67d2ba44b1 - name: Reset Docker Containers run: docker compose down --volumes --remove-orphans - name: Build Adapter Dependencies run: pnpm exec turbo run build --filter="$FILTER..." - name: Start Docker Containers if: matrix.compose_services != '' run: | read -r -a compose_services <<< "$COMPOSE_SERVICES" for startup_attempt in 1 2; do if docker compose up -d --wait --wait-timeout 60 "${compose_services[@]}"; then exit 0 fi if [[ "$startup_attempt" -eq 2 ]]; then exit 1 fi echo "Container startup failed; resetting and retrying once." docker compose ps --all || true docker compose logs --no-color "${compose_services[@]}" || true if ! docker compose down --volumes --remove-orphans; then echo "::warning::Container cleanup failed; retrying startup with remaining resources." fi done - name: Adapter Integration run: pnpm e2e:integration --filter="$FILTER" - name: Docker Compose Diagnostics if: failure() && hashFiles('docker-compose.yml') != '' && matrix.compose_services != '' run: | read -r -a compose_services <<< "$COMPOSE_SERVICES" docker compose ps --all || true docker compose logs --no-color "${compose_services[@]}" || true # Capture container exit and OOM state without masking the test failure. # cspell:ignore pids Pids for compose_service in "${compose_services[@]}"; do container_id="$(docker compose ps --all --quiet "$compose_service")" if [[ -n "$container_id" ]]; then docker inspect --format 'name={{.Name}} status={{.State.Status}} exit={{.State.ExitCode}} oom={{.State.OOMKilled}} error={{.State.Error}}' "$container_id" || true docker inspect --format 'name={{.Name}} pids_limit={{.HostConfig.PidsLimit}} memory_limit={{.HostConfig.Memory}} memory_swap={{.HostConfig.MemorySwap}}' "$container_id" || true image_id="$(docker inspect --format '{{.Image}}' "$container_id" || true)" if [[ -n "$image_id" ]]; then docker image inspect --format 'image_id={{.Id}} repo_digests={{json .RepoDigests}}' "$image_id" || true fi fi done - name: Stop Docker Containers if: always() && hashFiles('docker-compose.yml') != '' run: docker compose down --volumes --remove-orphans e2e: runs-on: ubuntu-latest needs: [smoke, integration, adapter-integration] if: always() steps: - uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # v1.2.2 with: jobs: ${{ toJSON(needs) }}