name: Load Tests (K6) on: workflow_dispatch: inputs: suite: description: 'Test suite to run' required: true default: 'all' type: choice options: - all - auth - listings - search - search-advanced - admin - mcp - payments concurrency: group: load-test-${{ github.ref }} cancel-in-progress: true jobs: load-test: name: K6 Load Test — ${{ inputs.suite }} runs-on: ubuntu-latest timeout-minutes: 20 services: postgres: image: postgis/postgis:16-3.4 env: POSTGRES_DB: goodgo_test POSTGRES_USER: goodgo POSTGRES_PASSWORD: goodgo_test_secret ports: - 5432:5432 options: >- --health-cmd "pg_isready -U goodgo -d goodgo_test" --health-interval 10s --health-timeout 5s --health-retries 5 env: DATABASE_URL: postgresql://goodgo:goodgo_test_secret@localhost:5432/goodgo_test NODE_ENV: test JWT_SECRET: load-test-jwt-secret-key JWT_REFRESH_SECRET: load-test-refresh-secret-key steps: - name: Checkout uses: actions/checkout@v4 - name: Install K6 run: | sudo gpg -k sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D68 echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list sudo apt-get update sudo apt-get install k6 - name: Install pnpm uses: pnpm/action-setup@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: 22 cache: pnpm - name: Install dependencies run: pnpm install --frozen-lockfile - name: Run database migrations run: pnpm db:migrate:deploy - name: Build and start API run: | pnpm --filter @goodgo/api run build pnpm --filter @goodgo/api run start & sleep 10 - name: Run load tests run: | mkdir -p results if [ "${{ inputs.suite }}" = "all" ]; then for f in load-tests/scripts/*.js; do name=$(basename "$f" .js) echo "=== Running $name ===" k6 run --out json="results/${name}.json" "$f" || true done else k6 run --out json="results/${{ inputs.suite }}.json" \ "load-tests/scripts/${{ inputs.suite }}.js" fi - name: Upload results if: ${{ !cancelled() }} uses: actions/upload-artifact@v4 with: name: k6-results-${{ inputs.suite }} path: results/ retention-days: 30