{
  "doc": {
    "id": "accessibility/guides/report-run-checks-github",
    "title": "Report Run Checks as GitHub pull request statuses in Cypress Accessibility",
    "description": "Post Cypress Accessibility Run Checks as GitHub commit statuses so score and failed-element thresholds block a pull request merge.",
    "section": "accessibility",
    "source_path": "/llm/markdown/accessibility/guides/report-run-checks-github.md",
    "version": "8d82546d64f56f8552b1f2cba6e27dab5f929d15",
    "updated_at": "2026-11-07T17:30:41.906Z",
    "headings": [
      {
        "id": "accessibility/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": "accessibility/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": " let you encode accessibility thresholds in your App Quality configuration, such as a minimum "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/accessibility/core-concepts/accessibility-score.md",
            "children": [
              {
                "type": "text",
                "value": "accessibility score"
              }
            ]
          },
          {
            "type": "text",
            "value": " or a maximum number of failing elements, and have Cypress Cloud evaluate them on every recorded run. To surface those results on a pull request, fetch them in CI with `getCheckResults()` and post one commit status per applicable check."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "This guide covers the GitHub workflow for posting Run Check statuses. Similar techniques apply to other version control contexts. For custom policy logic the built-in assertion types don't cover, such as allowlisting known failing rules or comparing against a baseline, use the "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/accessibility/connect-and-extend/results-api.md",
            "children": [
              {
                "type": "text",
                "value": "Results API"
              }
            ]
          },
          {
            "type": "text",
            "value": " approach in "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/accessibility/guides/block-pull-requests.md",
            "children": [
              {
                "type": "text",
                "value": "Block pull requests and set policies"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "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. 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 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": " - accessibility assertion types, view matching, and run scoping"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/accessibility/guides/block-pull-requests.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "Block pull requests and set policies"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": " - custom Results API policies"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/accessibility/connect-and-extend/results-api.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "Results API"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": " - fetch per-rule and per-view accessibility results in CI"
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  },
  "token_estimate": 693
}