{
  "doc": {
    "id": "cloud/guides/report-run-checks-github",
    "title": "Report Run Checks as GitHub pull request statuses",
    "description": "Post each Cypress Cloud Run Check as a GitHub commit status so failed quality gates block a pull request merge.",
    "section": "cloud",
    "source_path": "/llm/markdown/cloud/guides/report-run-checks-github.md",
    "version": "4a645eeb4b355bfca7d7bb576e96889b8b571465",
    "updated_at": "2026-11-05T01:52:34.491Z",
    "headings": [
      {
        "id": "cloud/guides/report-run-checks-github#report-run-checks-as-github-pull-request-statuses",
        "text": "Report Run Checks as GitHub pull request statuses",
        "level": 1
      },
      {
        "id": "cloud/guides/report-run-checks-github#see-also",
        "text": "See also",
        "level": 2
      }
    ]
  },
  "content": {
    "type": "root",
    "children": [
      {
        "type": "heading",
        "depth": 1,
        "children": [
          {
            "type": "text",
            "value": "Report Run Checks as GitHub pull request statuses"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/cloud/features/checks.md",
            "children": [
              {
                "type": "text",
                "value": "Run Checks"
              }
            ]
          },
          {
            "type": "text",
            "value": " evaluate recorded runs in Cypress Cloud against the thresholds you define: failed tests, flaky tests, accessibility scores, UI Coverage, and more. To turn those results into a merge gate, fetch them in CI with `getCheckResults()` and post one commit status per applicable check."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Install `@cypress/extract-cloud-results` as described in the "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/accessibility/connect-and-extend/results-api.md#Installation",
            "children": [
              {
                "type": "text",
                "value": "Results API"
              }
            ]
          },
          {
            "type": "text",
            "value": " guide, which also lists the "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/accessibility/connect-and-extend/results-api.md#Supported-CI-Providers",
            "children": [
              {
                "type": "text",
                "value": "supported CI providers"
              }
            ]
          },
          {
            "type": "text",
            "value": ". Run the status script in the same CI job that recorded the run, after `cypress run --record`. For the full `getCheckResults()` response shape and options, see "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/cloud/features/checks.md#Using-check-results-in-CI",
            "children": [
              {
                "type": "text",
                "value": "Using check results in CI"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "This is separate from the Cypress "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/cloud/integrations/github.md#Status-checks",
            "children": [
              {
                "type": "text",
                "value": "GitHub integration"
              }
            ]
          },
          {
            "type": "text",
            "value": ", which reports per-run-group or per-spec test pass/fail. Run Check statuses report specific thresholds that you configure, including Cypress Accessibility and UI Coverage assertions if relevant."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "This GitHub Actions workflow records a run, then posts one "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://docs.github.com/en/rest/commits/statuses",
            "children": [
              {
                "type": "text",
                "value": "commit status"
              }
            ]
          },
          {
            "type": "text",
            "value": " per applicable "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/cloud/features/checks.md",
            "children": [
              {
                "type": "text",
                "value": "Run Check"
              }
            ]
          },
          {
            "type": "text",
            "value": " to the pull request. A failed check shows as a failing status on the pull request, and you can make the statuses required in your branch protection rules."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": ".github/workflows/cypress.yml"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "name: Cypress\non: pull_request\n\npermissions:\n  contents: read\n  statuses: write\n\njobs:\n  cypress:\n    runs-on: ubuntu-latest\n    env:\n      CYPRESS_PROJECT_ID: abc123\n      CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}\n    steps:\n      - uses: actions/checkout@v4\n      - run: npm ci\n      # Failing tests fail this step, but the checks still need to be reported.\n      - run: npx cypress run --record\n        continue-on-error: true\n      - run: npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz\n      - run: node scripts/post-check-statuses.js\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "scripts/post-check-statuses.js"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "const fs = require('fs')\nconst { getCheckResults } = require('@cypress/extract-cloud-results')\n\nconst STATES = { passed: 'success', failed: 'failure' }\n\n// On pull_request events, GITHUB_SHA is a merge commit that GitHub creates.\n// Statuses only show on the pull request when they're posted to its head commit.\nconst event = JSON.parse(fs.readFileSync(process.env.GITHUB_EVENT_PATH, 'utf8'))\nconst sha = event.pull_request?.head.sha ?? process.env.GITHUB_SHA\n\nconst main = async () => {\n  const results = await getCheckResults()\n  const checks = (results.checks ?? []).filter(\n    (check) => check.status !== 'not-applicable'\n  )\n\n  for (const check of checks) {\n    const missed = check.assertionResults\n      .filter((assertion) => assertion.status !== 'passed')\n      .map(({ type, value, status }) => `${type} ${value} (${status})`)\n\n    const response = await fetch(\n      `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/statuses/${sha}`,\n      {\n        method: 'POST',\n        headers: {\n          authorization: `Bearer ${process.env.GITHUB_TOKEN}`,\n          accept: 'application/vnd.github+json',\n        },\n        body: JSON.stringify({\n          context: `Cypress check: ${check.name}`,\n          state: STATES[check.status] ?? 'error',\n          description: (missed.length\n            ? `Missed: ${missed.join('; ')}`\n            : 'All assertions passed'\n          ).slice(0, 140),\n          target_url: `${results.runUrl}/properties`,\n        }),\n      }\n    )\n\n    if (!response.ok) {\n      throw new Error(`GitHub responded ${response.status}`)\n    }\n  }\n}\n\nmain().catch((error) => {\n  console.error(error.message)\n  process.exit(1)\n})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The script skips `not-applicable` checks, so a check scoped to `release/.*` branches only appears on pull requests from those branches. GitHub limits a status description to 140 characters, so the script truncates it and links each status to the run for details."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "See also"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/cloud/features/checks.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "Run Checks"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": " - define assertions and scope them to branches and tags"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/cloud/integrations/github.md#Status-checks",
                    "children": [
                      {
                        "type": "text",
                        "value": "GitHub integration"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": " - built-in commit statuses for test results"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/cloud/features/flaky-test-management.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "Flaky Test Management"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": " - flake detection that `run.flakyTests.max` reads"
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  },
  "token_estimate": 657
}