Documentation
Guides

QA: Poll Trigger Executor & GitHub PR Template

Testing guidelines for the poll trigger sweep infrastructure and the new github-pr-opened poll template.

This document covers testing guidelines for the poll trigger executor, which enables poll-type runner triggers to detect new events from MCP providers and fire runner pipelines.


Prerequisites

  1. Apply migration 035_poll_trigger_cursor.sql (run supabase db reset or apply manually)
  2. Verify poll_cursor JSONB column exists on runner_triggers
  3. Verify partial index idx_runner_triggers_poll_sweep exists
  4. A GitHub MCP server must be connected with valid OAuth credentials
  5. Set CRON_SECRET env var for testing the cron endpoint

1. Migration

Test: poll_cursor column exists

SELECT column_name, data_type
FROM information_schema.columns
WHERE table_name = 'runner_triggers' AND column_name = 'poll_cursor';
  • Returns one row with data_type = 'jsonb'

Test: Partial index exists

SELECT indexname FROM pg_indexes
WHERE tablename = 'runner_triggers' AND indexname = 'idx_runner_triggers_poll_sweep';
  • Returns one row

Test: Existing triggers unaffected

  • Existing cron/webhook/manual triggers still work after migration
  • poll_cursor is null for all existing rows

2. Poll Template: github-pr-opened

Test: Template appears in template list

  1. Call getTemplatesForProvider('github') or inspect POLL_TEMPLATES
  2. Verify github-pr-opened exists with:
    • label: "PR opened or updated"
    • providerKey: "github"
    • params.repo: required, placeholder "owner/repo"
    • defaultIntervalMinutes: 5

Test: Template appears in trigger form UI

  1. Open a Runner's trigger configuration
  2. Select "Integration" trigger kind
  3. Select "GitHub" provider
  4. Verify "PR opened or updated" appears in the template dropdown
  5. Verify a "Repository" field appears with placeholder "owner/repo"

3. Poll Sweep — Cron Endpoint

Test: Cron endpoint includes poll sweep results

curl -H "Authorization: Bearer $CRON_SECRET" \
  http://localhost:3000/api/cron/runners
  • Response includes polls object with { checked, fired, runIds }
  • When no poll triggers exist: polls.checked === 0, polls.fired === 0

Test: Poll triggers are skipped when not due

  1. Create a runner with a poll trigger (intervalMinutes: 5)
  2. Fire the cron endpoint
  3. Immediately fire the cron endpoint again
  4. Second invocation should show polls.checked === 0 (interval not elapsed)

Test: Disabled poll triggers are skipped

  1. Create a poll trigger with enabled: false
  2. Fire the cron endpoint
  3. Trigger is not checked (doesn't appear in errors or fired)

Test: Inactive runners are skipped

  1. Create a runner with status: 'draft' and an enabled poll trigger
  2. Fire the cron endpoint
  3. Trigger is not checked

4. Poll Sweep — GitHub PR Detection

Test: First run sets baseline without firing

  1. Create a runner + poll trigger with template github-pr-opened, repo owner/repo
  2. Ensure the repo has at least one open PR
  3. Fire the cron endpoint
  4. polls.fired === 0 (first run is baseline only)
  5. poll_cursor in the database is now set with last_updated_at and seen_ids

Test: New PR detected on second run

  1. After baseline is set (step above), open a new PR in the repo
  2. Wait for intervalMinutes to elapse (or set interval to 1 minute)
  3. Fire the cron endpoint
  4. polls.fired === 1
  5. A new runner_runs row exists with input.event === 'pr_opened'
  6. input.pull_request contains the PR object
  7. input.repository contains { owner, name, full_name }

Test: Updated PR detected

  1. After baseline is set, push a new commit to an existing open PR
  2. Fire the cron endpoint
  3. polls.fired === 1
  4. input.event === 'pr_updated'

Test: No duplicate fires

  1. Fire the cron endpoint after a PR was already detected
  2. Without any new PR activity
  3. polls.fired === 0
  4. poll_cursor.last_updated_at is unchanged

Test: Invalid repo param

  1. Create a poll trigger with params.repo set to invalid (no slash)
  2. Fire the cron endpoint
  3. Error logged: INVALID_REPO_PARAM
  4. No runs created

Test: Cursor caps seen_ids at 200

  1. (Simulated) Set poll_cursor.seen_ids to an array of 250 IDs
  2. Fire the cron endpoint
  3. After update, seen_ids length is <= 200

5. Poll Sweep — Other GitHub Templates

Test: github-new-issue detects new issues

  1. Create a poll trigger with template github-new-issue
  2. Fire cron endpoint to set baseline
  3. Create a new issue in the repo
  4. Fire cron endpoint again
  5. input.event === 'issue_opened'
  6. PRs appearing in the issues endpoint are filtered out

Test: github-new-commit detects new commits

  1. Create a poll trigger with template github-new-commit, branch main
  2. Fire cron endpoint to set baseline
  3. Push a commit to main
  4. Fire cron endpoint again
  5. input.event === 'new_commit'
  6. input.branch === 'main'

6. MCP Connection Handling

Test: OAuth token refresh

  1. Configure a GitHub MCP server with an expired OAuth token (but valid refresh token)
  2. Fire the cron endpoint with a poll trigger pointing to that server
  3. Token is refreshed automatically
  4. mcp_credentials.encrypted_oauth is updated with new token
  5. Poll succeeds

Test: OAuth token revoked

  1. Configure a GitHub MCP server with a revoked refresh token
  2. Fire the cron endpoint
  3. Error logged: OAUTH_REFRESH_FAILED
  4. No runs created
  5. Other triggers continue processing (one failure doesn't block the sweep)

Test: MCP server unreachable

  1. Configure an MCP server with an invalid URL
  2. Fire the cron endpoint
  3. Error logged with connection failure details
  4. Sweep continues processing remaining triggers

Test: MCP tool call timeout

  1. Simulate a slow MCP server (> 15s response time)
  2. AbortController fires, error logged
  3. Sweep continues processing remaining triggers

7. Pipeline Execution

Test: Fired runs execute pipelines

  1. Create a runner with a poll trigger and at least one agent step
  2. Trigger a new PR event
  3. Fire the cron endpoint
  4. runner_runs row created with status: 'pending'
  5. Pipeline executes (status progresses to running then completed or failed)
  6. runner_run_steps rows created for each step

Test: Multiple new events create multiple runs

  1. Open 3 new PRs between cron ticks
  2. Fire the cron endpoint
  3. 3 separate runner_runs rows created
  4. All 3 pipelines execute

Test: input_defaults merged with event data

  1. Set input_defaults on the trigger: { "review_style": "thorough" }
  2. Trigger a PR event
  3. Run input contains both review_style and event/pull_request fields

8. Regression: Existing Trigger Types

Test: Cron triggers still fire

  • Cron triggers continue to work as before
  • Response JSON still includes runners object

Test: Webhook triggers still fire

  • POST /api/runners/webhooks/{token} still works
  • Pipeline executes normally

Test: Scheduled tasks still sweep

  • Response JSON still includes tasks object
  • Scheduled task sweep runs in parallel with poll sweep
Docs last updated May 11, 2026