name: Heavy Tests # Heavy ops-shape tests under tests/heavy/. Cost minutes per run; NOT part # of default PR CI. Two triggers: # - Nightly schedule (catches regressions within 24h of merge to master). # - On-demand opt-in via PR label `heavy-tests` (slow loop kept off by default). # - Manual workflow_dispatch for triage. # # See CLAUDE.md "tests/heavy/*.sh" entry and tests/heavy/README.md. on: schedule: - cron: '17 8 * * *' # 08:17 UTC daily — staggered to avoid noisy slots pull_request: # `synchronize` + `reopened` fire on subsequent pushes / reopens — without # them, a PR labeled `heavy-tests` would NEVER re-run heavy on later # commits. The job-level `if:` below filters to PRs that still carry the # label so we don't fan out on unrelated label changes. types: [labeled, synchronize, reopened] workflow_dispatch: permissions: contents: read # When a PR gets the heavy-tests label, cancel any in-flight heavy-tests run on # the same ref so we only ever measure the latest commit. concurrency: group: heavy-tests-${{ github.ref }} cancel-in-progress: true jobs: heavy: name: Heavy tests # On pull_request: only run when the PR currently carries the `heavy-tests` # label. Works for all three trigger types (labeled, synchronize, reopened) # because `contains(labels.*.name, ...)` reads the live label set, not the # event payload's `label.name` (which is only populated for `labeled`). if: | github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'heavy-tests') runs-on: ubuntu-latest timeout-minutes: 30 services: postgres: image: pgvector/pgvector:pg16 env: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: gbrain_test ports: - 5432:5432 options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 with: bun-version: 1.3.13 - run: bun install - name: Run heavy tests env: DATABASE_URL: postgresql://postgres:postgres@localhost:5432/gbrain_test run: bun run test:heavy # The heavy runner writes per-script logs to ~/.gbrain/audit/ on every # run. Upload those + the rss workload JSON on failure for triage # without re-running locally. # # actions/upload-artifact runs as a node action — `~` is NOT expanded by # the shell here. Stage logs into the workspace first, then upload from # the stable workspace-relative path. - name: Stage heavy-test logs into workspace if: always() run: | mkdir -p heavy-artifacts cp -r "$HOME/.gbrain/audit"/heavy-* heavy-artifacts/ 2>/dev/null || true cp tests/heavy/rss-baseline.json heavy-artifacts/ 2>/dev/null || true - name: Upload heavy-test artifacts if: always() uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: heavy-tests-${{ github.run_id }}-${{ github.run_attempt }} path: heavy-artifacts/ retention-days: 14 if-no-files-found: ignore