View all services
Talk to QA Advisor
Browse the Knowledge Hub211 resources
Tools Library · Review and guide

GitHub review for QA teams: pricing, alternatives and setup

GitHub hosts Git repositories and wraps them in pull requests with code review, branch protection, issues and projects, Actions for CI/CD, Packages, and security features such as Dependabot. For test teams it is where test code is reviewed, where suites run on every change, and where a failing suite can block a merge.

QAble has evaluated this tool and works alongside it. The factual sections are complete; our view is bounded to what we have actually seen rather than a long-term verdict.

last reviewed
13 October 2026
version covered
GitHub.com, October 2026
licence
Freemium

Reviewed by Viral Patel

Co-Founder, QAbleLast reviewed 13 October 2026

At a glance

GitHub at a glance

Official site
Vendor
Microsoft
Category
Version control, Collaboration, CI/CD
Licence
Freemium
Platforms
Cloud, Enterprise Server
Integrates with
GitHub Actions, Jira, Slack, SonarQube
First released
2008
Version reviewed
GitHub.com, October 2026

Verdict

Our verdict on GitHub

Strengths

  • Required status checks block merging while tests fail, enforced by the server rather than by habit
  • CODEOWNERS requests review from the test owners whenever a pull request touches their files
  • Actions is built in, and free on standard runners for public repositories
  • Issue forms turn bug reports into structured fields such as version, browser, steps and logs
  • Merge queues test each pull request against main plus everything queued ahead of it
  • The gh CLI watches checks, reruns failed jobs and downloads artefacts from the terminal

Weaknesses

  • Protected branches and code owners need a paid plan for private repositories
  • Merge queues on private repositories need GitHub Enterprise Cloud
  • No built-in test case management; teams use issues or a separate tool
  • Secret Protection and Code Security for private repositories are separate per-committer licences
  • macOS runner minutes cost about ten times the Linux 2-core rate

Our take

For a QA team, GitHub is where test code is reviewed and where test results meet the change they judge. The parts that matter most are required status checks and reviews, which stop a pull request merging while its tests fail; CODEOWNERS, which sends changes to test code to the people who own it; Actions, which runs the suites; and issue forms, which give bug reports a consistent shape. QAble has evaluated GitHub in this role rather than administered it at organisation scale, so treat this as a bounded take. The detail most often missed is plan gating: on the free plans, protected branches and code owners work only in public repositories, so a private repository needs Pro, Team or Enterprise before a failing suite can actually block a merge.

We have evaluated this tool rather than maintained a long-running suite on it, so this is a bounded view rather than a long-term verdict. The rest of this page is factual.

How it works

How GitHub works

Pull requests carry review and checks together

A pull request compares a head branch with a base branch and gathers everything needed to decide whether to merge: the diff, review comments and approvals, and status checks. Checks are reported against the head commit by GitHub Actions or by any external CI through the API, so every new push starts a fresh set of checks for the new commit. That is why a green pull request can turn yellow after a one-line fix, and why approvals can be dismissed automatically when new commits change the diff. Merging can create a merge commit, squash everything into one commit or rebase, as the repository allows.

Branch protection turns tests into a gate

Protection rules on a branch such as main can require a pull request, a number of approvals, review from code owners, and named status checks that must pass. Strict mode, the default, also requires the branch to be up to date with the base, so the checks have run against the code that will actually be merged. Required checks are matched by name, which is why GitHub advises unique job names across workflows. By default, rules do not bind repository administrators unless you choose to include them. Protected branches are available for public repositories on every plan, and for private repositories on Pro, Team and Enterprise.

Actions runs workflows where the code lives

Workflows are YAML files under .github/workflows, triggered by repository events such as pull_request, push, merge_group, a schedule or a manual dispatch. Each job runs on a fresh GitHub-hosted virtual machine, Linux, Windows or macOS, or on a self-hosted runner you operate. For private repositories, hosted minutes beyond the plan’s monthly allowance are billed per minute at a rate that depends on the runner, while public repositories on standard runners and all self-hosted runners incur no Actions charge. Artefacts such as reports and screenshots share a storage allowance with Packages.

Plans gate collaboration features, not repositories

Every plan includes unlimited public and private repositories. What changes between Free, Team and Enterprise is governance: protected branches, required reviewers and code owners in private repositories from Team, and SAML single sign-on, Enterprise Managed Users, audit log streaming and a larger Actions allowance on Enterprise Cloud. GitHub Enterprise Server is the self-hosted edition. Security scanning for private repositories is sold separately as Secret Protection and Code Security, which require Team or Enterprise, and Copilot has its own plans.

Strengths

What it does well

Merge gates made of tests

Marking a test job as a required status check means no pull request merges while it fails, regardless of who approves. Combined with required approvals and dismissal of stale approvals when new commits change the diff, it makes “tests pass before merge” a property of the repository rather than a team agreement that erodes under deadline pressure.

Test code routed to its owners

A CODEOWNERS file maps paths to people or teams, and GitHub requests their review automatically when a pull request changes those paths. With code owner review required, a developer cannot weaken an assertion or delete a flaky test without someone from QA seeing it. Owners must have write access, and the last matching pattern in the file takes precedence.

Structured bug reports with issue forms

Issue forms, still in public preview, are YAML definitions in .github/ISSUE_TEMPLATE that present a bug report as a form with inputs, dropdowns, checkboxes, file uploads and required fields. Answers become the issue body, labels and assignees apply automatically, and every report arrives with the environment, steps and logs a tester needs to reproduce it.

Merge queues for busy branches

A merge queue takes pull requests that have passed their checks, combines each with the latest base branch and the pull requests ahead of it, and runs the required checks again before merging. It gives the guarantee of strict up-to-date checks without authors rebasing and re-running repeatedly. Workflows must trigger on the merge_group event, or the queued checks never report.

Results where reviewers look

A step can append Markdown to a job summary through the GITHUB_STEP_SUMMARY file, which appears on the workflow run page, and workflow commands such as ::error file=...,line=... create annotations that show on the changed lines of the pull request. Uploaded artefacts keep reports, traces and screenshots attached to the run for download.

Dependency alerts for test frameworks

Test frameworks pull in large dependency trees. The dependency graph and Dependabot alerts are included in every plan, and Dependabot version updates open pull requests for npm, Maven, pip, Docker and GitHub Actions dependencies on a schedule, so the test stack is upgraded through the same review and checks as product code.

Pricing

GitHub pricing and licensing

GitHub is a hosted service with a free plan and paid per-user plans named Team and Enterprise; Enterprise is available as the hosted Enterprise Cloud or the self-hosted Enterprise Server. Actions minutes, artefact and package storage, Codespaces, Git LFS, Advanced Security and Copilot are metered or licensed on top. For test teams, the costs that grow are Actions minutes on private repositories, especially macOS, and storage for screenshots, videos and traces.

  • Free: unlimited public and private repositories and collaborators, 2,000 Actions minutes and 500 MB of storage a month for private repositories. Protected branches and code owners work on public repositories only.
  • Team: adds protected branches, required reviewers, repository rules and code owners in private repositories, with 3,000 minutes and 2 GB. Listed on github.com/pricing on 13 October 2026 at $4 per user per month for the first 12 months.
  • Enterprise: adds SAML single sign-on, Enterprise Managed Users, audit log streaming and the self-hosted Server option, with 50,000 minutes and 50 GB on Enterprise Cloud. Listed at $21 per user per month for the first 12 months, on the same date.
  • Actions beyond the allowance is billed per minute by runner type. GitHub’s billing docs listed $0.006 for Linux 2-core, $0.010 for Windows and $0.062 for macOS as list rates; public repositories on standard runners and self-hosted runners incur no Actions charge.
  • Add-ons: Secret Protection and Code Security are licensed per active committer, meaning anyone who pushed to an enabled repository in the last 90 days, and need Team or Enterprise. Copilot has separate plans, including a free one.
  • Hidden costs: artefact storage is metered hourly against the shared allowance, so set retention-days on uploads of screenshots and videos rather than relying on defaults.

Checked against the vendor’s own pages on 13 October 2026. Pricing changes; confirm on the official site before buying.

Getting started

Getting started with GitHub

Setup, step by step

  1. Create an organisation for the team and choose a plan; private repositories need Team or above for protected branches.
  2. Install the GitHub CLI and run gh auth login.
  3. Add the workflow below as .github/workflows/tests.yml, so tests run on every pull request and in the merge queue.
  4. In the repository settings, protect main: require a pull request, one approval and the tests status check.
  5. Add a CODEOWNERS file so changes under tests/ request review from the QA team.
  6. Open a pull request with a deliberately failing test and confirm the merge button is blocked.

Install

# Windows
winget install --id GitHub.cli --source winget
# macOS
brew install gh

gh auth login
gh repo clone example/shop

A first example

# .github/workflows/tests.yml
name: tests
on:
  pull_request:
  merge_group:            # without this, merge queue checks never report
jobs:
  tests:                  # the required check name: keep it unique across workflows
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v7
        with:
          node-version: 24
          cache: npm
      - run: npm ci
      - run: npx playwright install --with-deps
      - run: npx playwright test
      - name: Summary on the run page
        if: always()
        run: echo "### Playwright run for ${{ github.sha }}" >> "$GITHUB_STEP_SUMMARY"
      - uses: actions/upload-artifact@v7
        if: failure()
        with:
          name: playwright-report
          path: playwright-report
          retention-days: 14

What trips people up first

A required check that never reports. The pull request shows the tests check as expected or pending, and the merge stays blocked although nothing failed. The usual causes are a check name in the protection rule that does not match the job name, a workflow skipped by a paths or branches filter, which GitHub documents as leaving its checks pending, and a merge queue whose workflow lacks the merge_group trigger. Match names exactly, keep job names unique across workflows, and avoid path filters on workflows whose checks are required; skip work inside the job instead.

In practice

Using GitHub in practice

Protecting main with tests and test owners

Set the rule on main to require a pull request, at least one approval, dismissal of stale approvals, review from code owners, and the tests check, with the branch up to date before merging. Then write a CODEOWNERS file that gives QA ownership of the test directories, the test configuration and the workflows that run them. Because the last matching pattern wins, put broad rules first and specific ones after. Decide deliberately whether administrators are bound by the rules; by default they are not, which is often how failing tests reach main. On Team and Enterprise, rulesets can apply the same rules across many repositories at once.

# .github/CODEOWNERS: the last matching pattern takes precedence
*                       @example/developers
/tests/                 @example/qa
/tests/payments/        @example/qa-payments
/playwright.config.ts   @example/qa
/.github/workflows/     @example/platform @example/qa

Bug reports that arrive reproducible

An issue form makes the fields a tester needs mandatory instead of hoped for. Ask for the build or version, the environment, the browser or device, numbered steps, expected and actual results, and logs, and let the form apply labels so triage queries work. Keep the form short enough that people use it: every required field is friction for someone reporting from outside the team. Issue forms are still in public preview, so check the syntax reference when a field type behaves unexpectedly, and keep a blank issue option for things that are not bugs.

# .github/ISSUE_TEMPLATE/bug.yml
name: Bug report
description: Something does not work as specified.
labels: ["bug", "triage"]
body:
  - type: input
    id: build
    attributes:
      label: Build or version
      placeholder: e.g. 4.12.0 or the commit SHA
    validations:
      required: true
  - type: dropdown
    id: browser
    attributes:
      label: Browser
      multiple: true
      options: [Chrome, Firefox, Safari, Edge, Not applicable]
  - type: textarea
    id: steps
    attributes:
      label: Steps to reproduce, expected and actual result
    validations:
      required: true
  - type: textarea
    id: logs
    attributes:
      label: Logs or console output
      render: shell

Putting results on the pull request

A red cross on a check tells a reviewer that something failed, not what. Three mechanisms close the gap. A job summary written to GITHUB_STEP_SUMMARY puts counts, failing test names and links on the run page in Markdown. Workflow commands such as ::error with a file and line put an annotation on the changed line in the pull request diff, which is where a developer is already looking. And uploaded artefacts keep the HTML report, traces and screenshots for download. Most test runners can output JUnit XML, and community actions on the Marketplace turn it into check annotations, but review a third-party action’s code and pin it to a commit before granting it access to your repository.

# In a workflow step: a summary table on the run page
{
  echo "### End-to-end results"
  echo "| Passed | Failed | Skipped |"
  echo "| --- | --- | --- |"
  echo "| $PASSED | $FAILED | $SKIPPED |"
} >> "$GITHUB_STEP_SUMMARY"

# An annotation shown on the matching line of the pull request diff
echo "::error file=tests/checkout/coupon.spec.ts,line=42,title=Coupon test failed::Expired coupon was accepted"

Working with checks from the terminal

The GitHub CLI shortens the loop between a failing check and a fix. gh pr checks with --watch follows the checks on the current branch’s pull request until they finish, and --required limits it to the checks that gate merging. gh run view with --log-failed prints only the logs of failed steps, which is usually all you need. gh run rerun with --failed reruns just the failed jobs and their dependencies, and gh run download fetches artefacts such as reports by name. Rerunning should be a diagnostic, not a habit: a test that passes on rerun is flaky, and it belongs in a tracked issue rather than in the team’s muscle memory.

gh pr checks --watch --required      # follow the merge-gating checks
gh run list --workflow tests.yml --limit 5
gh run view <run-id> --log-failed     # only the failed steps' logs
gh run rerun <run-id> --failed        # rerun failed jobs and their dependencies
gh run download <run-id> -n playwright-report

Keeping the test stack current with Dependabot

A test framework, its browser binaries, the Docker images it runs in and the actions in its workflows all go stale. A dependabot.yml file schedules version update pull requests for each ecosystem, and groups combine related packages, such as everything named after Playwright, into one pull request, so an upgrade arrives as one change with one test run rather than five. Because those pull requests pass through the same branch protection and required checks, an upgrade that breaks the suite is caught before merge. Include the github-actions ecosystem: action versions drift as quickly as packages do.

# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
    groups:
      playwright:
        patterns: ["@playwright/*", "playwright*"]
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"

Pitfalls

Common pitfalls

Required checks stuck pending after adding path filters

Why it happens: GitHub documents that a workflow skipped by a paths, branches or commit-message filter leaves its checks pending, and a pull request that requires them cannot merge.

The fix: Do not filter required workflows by path. Run the workflow always and decide inside it, for example with a job that detects changed files and skips the expensive steps.

A skipped job quietly passing the gate

Why it happens: The opposite case: a job skipped by an if condition reports success, and GitHub states it will not block merging even when it is a required check.

The fix: Make sure the required job itself runs, and put conditions on its steps or on upstream jobs. Review if expressions on required jobs as carefully as the tests.

Ambiguous results from duplicate job names

Why it happens: Required checks are matched by name, so two workflows each with a job called test produce ambiguous status results, which GitHub warns can block pull requests from merging.

The fix: Give every job a name unique across all workflows in the repository, and use that exact name in the protection rule.

Merge queue entries that never complete

Why it happens: The merge queue creates temporary branches and fires the merge_group event; workflows that trigger only on pull_request never run there, so the required checks never report.

The fix: Add merge_group to the on block of every workflow that provides a required check, as in the snippet above.

Expecting branch protection on a free private repository

Why it happens: Protected branches and code owners on the free plans apply to public repositories only, so on a private repository the settings that would block a failing merge are not available.

The fix: Use Pro for a personal account or Team for an organisation, or make the repository public if that is appropriate, before relying on tests as a merge gate.

Artefact storage filling with screenshots and videos

Why it happens: Every run that uploads traces, videos and screenshots adds to storage that is metered hourly and shared with Packages, and the default retention keeps them long after anyone looks.

The fix: Upload artefacts only on failure, set retention-days on each upload, and keep large media out of passing runs.

Compared

GitHub alternatives compared

ToolBuilt-in CISelf-managed editionTest case managementFree plan limitFree CI allowance
GitHubGitHub ActionsGitHub Enterprise ServerNone built inUnlimited collaborators2,000 minutes a month, private repositories
GitLabGitLab CI/CDGitLab Self-ManagedTest cases, Ultimate tier only5 users per private top-level group400 compute minutes a month
BitbucketBitbucket PipelinesBitbucket Data CenterNone built inUp to 5 users50 build minutes
Azure DevOpsAzure PipelinesAzure DevOps ServerAzure Test Plans, paid access levelFirst 5 Basic users freeOne hosted job, 1,800 minutes a month

FAQ

Frequently asked questions

What are the best GitHub alternatives?

The alternatives most often weighed against GitHub are GitLab, Bitbucket and Azure DevOps. The comparison on this page sets them side by side on built-in ci, self-managed edition, test case management, free plan limit and free ci allowance, and the verdict above says where GitHub is the wrong choice and which of them to pick instead.

Is GitHub free for a test team?

Partly. The free plan includes unlimited public and private repositories and collaborators, plus 2,000 Actions minutes a month for private repositories. What it lacks for private repositories is the governance a test team relies on: protected branches, required reviewers and code owners, which need Team or Enterprise for an organisation, or Pro for a personal account. Public repositories get those features and free standard runners on every plan.

How do I make failing tests block a pull request?

Run the tests in a workflow triggered on pull_request, then add a branch protection rule or ruleset on main that requires a pull request and lists the test job as a required status check. Keep the job name unique, avoid path filters on that workflow, and add merge_group if you use a merge queue. On private repositories this needs Pro, Team or Enterprise.

Can GitHub manage test cases?

Not natively. GitHub has no test case, test run or test plan objects. Teams keep automated tests as code in the repository, track manual test work in issues and projects, or connect a test management tool. If built-in test management is a requirement, Azure DevOps has Azure Test Plans as a paid access level and GitLab offers test cases on its Ultimate tier.

GitHub or GitLab for a QA team?

Both host Git with merge gating, built-in CI and code owners. GitHub’s Free plan has no collaborator limit, while GitLab’s free tier on GitLab.com allows 5 users per private top-level group. GitLab bundles more into one product, including test cases on its Ultimate tier, and its self-managed edition suits organisations that cannot use a hosted service. The deciding factor is usually where the application code already lives.

Are self-hosted runners free on GitHub?

GitHub’s Actions billing documentation states that Actions usage is free for self-hosted runners and for public repositories using standard GitHub-hosted runners. You pay for the machines you run yourself, and for your time maintaining them. Larger GitHub-hosted runners are always billed, even for public repositories.

Why does my required check say expected or pending forever?

GitHub is waiting for a check with that exact name and nothing has reported it. Check that the name in the rule matches the job name, that the workflow is not skipped by a paths, branches or commit-message filter, which leaves checks pending by design, and that workflows used with a merge queue trigger on merge_group.

Does Dependabot cost extra?

No. The dependency graph and Dependabot alerts are included in every plan, and GitHub’s docs list Dependabot version updates as available for all repositories. What costs extra for private repositories are the Advanced Security products: Secret Protection for secret scanning and push protection, and Code Security for code scanning, dependency review and premium Dependabot features, licensed per active committer on Team or Enterprise.

Alternatives

GitHub alternatives worth weighing

GitLab

Single-platform DevOps suite spanning source, CI/CD, security scanning and deployment.

Bitbucket

Atlassian Git hosting, with the tightest Jira integration of any platform.

Resources

Where to go next

Ready

Picking the wrong tool costs more than picking late.

QAble advises on toolchain decisions and then implements them, with engineers who have run these tools on real delivery. Start with a free QA audit.

Talk to QA Advisor