Automated Test Runs on Pull Requests: CI Pipeline & Code Protection

Automated Test Runs on Pull Requests

Development and maintenance of all types of websites:

Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Our competencies:

Frequently Asked Questions

Latest works

  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1281
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1237
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    977
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    1026
  • image_website-sbh_0.webp
    Website development for SBH Partners
    1103
  • image_website-_0.webp
    Website development for Red Pear
    550

Automated Test Runs on Pull Requests

Imagine this: you just merged a PR into main, and a minute later production goes down with an error. It turns out the new module overwrote an old endpoint, and no test caught it. This scenario is familiar to many teams. We've been through it and since then have enforced a hard rule: every PR goes through an automated test pipeline. No green light — no merge. Automated test runs on PR are the basic defense against regressions. A developer cannot merge code that breaks existing functionality. This is not a replacement for code review, but a supplement: reviewers focus on logic, not on catching obvious bugs.

According to GitHub Actions documentation, dependency caching cuts installation time from 90 seconds to 5 seconds — 18 times faster. Matrix test execution lets you check different environment versions in parallel, speeding up the overall run by 3–4 times. This saves up to 40 hours per month on debugging. Our experience — over 5 years in CI/CD and 100+ configured pipelines — confirms that automated test runs pay off within the first sprint.

Why Automated Test Runs on PR Are Critical

Without this protection, you risk:

  • A broken CI on main — if a bug gets merged, the entire next sprint goes to fixing it.
  • Wasted time on code review — reviewers get distracted by errors that tests could catch.
  • Manual testing — the less routine, the higher the delivery speed.

Which Tests to Run and Which to Skip

Test Type Mandatory? When to Run Purpose
Linting Yes On every commit Consistent style, catch potential bugs
Unit tests Yes On every PR Check isolated logic
Integration tests Yes (DB/API) On every PR Component interaction
E2E No (on demand) Only for critical scenario changes Full user path check
Security tests Recommended Once a day or on release Find vulnerabilities

Pipeline Structure

A well-designed pipeline splits into parallel jobs with a fail-fast strategy:

# .github/workflows/pr.yml name: PR Tests on: pull_request: branches: [main, develop] concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true # Cancel old runs on new push jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: { node-version: 20, cache: npm } - run: npm ci - run: npm run lint && npm run type-check unit: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: { node-version: 20, cache: npm } - run: npm ci - run: npm test -- --coverage - uses: codecov/codecov-action@v4 with: token: ${{ secrets.CODECOV_TOKEN }} integration: runs-on: ubuntu-latest services: postgres: image: postgres:16 env: POSTGRES_DB: testdb POSTGRES_PASSWORD: test options: >- --health-cmd pg_isready --health-interval 5s --health-timeout 5s --health-retries 5 steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: { node-version: 20, cache: npm } - run: npm ci - run: npm run test:integration env: DATABASE_URL: postgresql://postgres:test@localhost:5432/testdb 

How to Set Up Caching to Speed Up the Pipeline

Without caching, npm ci on a cold runner takes 60–90 seconds. With caching — 5–10 seconds. Use the built-in cache in actions/setup-node or explicit via actions/cache:

# Cache node_modules based on package-lock.json - uses: actions/setup-node@v4 with: node-version: 20 cache: npm # Built-in cache in actions/setup-node # Or explicitly via actions/cache - uses: actions/cache@v4 with: path: ~/.npm key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} 

Impact of caching on speed:

Method Dependency installation time Total pipeline time
No cache 60–90 s 3–5 min
With cache (actions/setup-node) 5–10 s 1–2 min
Built-in cache + matrix 5–10 s per job 1–2 min (parallel)

Matrix Testing and Supporting Multiple Stacks

If the application must work on multiple Node.js or PHP versions, use a matrix:

strategy: matrix: node-version: [18, 20, 22] fail-fast: false # Run all versions even if one fails 

For Laravel projects, use parallel PHPUnit execution:

- name: Run PHPUnit run: php artisan test --parallel --coverage-clover=coverage.xml env: DB_CONNECTION: pgsql DB_DATABASE: testing - name: Upload coverage uses: codecov/codecov-action@v4 with: files: coverage.xml 

--parallel runs tests in parallel via brianium/paratest. On 200+ tests, it speeds up by 3–4 times.

Status Checks and Branch Protection

In GitHub Settings → Branches → Branch protection rules, add required status checks: lint, unit, integration. Merging into main without these checks is impossible.

Speed Optimization: Path Filtering and Test Splitting

  • Path filtering — run tests only when relevant files change (e.g., via paths in GitHub Actions).
  • Test splitting — distribute tests across multiple runners (GitHub Actions matrix).
  • Only changed modules — Jest --changedSince, pytest --testpaths.

Goal: pipeline completes within 5 minutes. Slower pipelines cause developers to ignore them.

Process of Setting Up and What’s Included in the Work

  1. Analyze current tests and project infrastructure.
  2. Design the pipeline: define jobs, matrices, caching.
  3. Implement GitHub Actions configuration tailored to your stack.
  4. Set up branch protection and required status checks.
  5. Test on a real PR, debug.
  6. Document the process and hand over to the team.

As a result, you get:

  • GitHub Actions configuration with caching and matrix
  • Status checks and branch protection rules
  • Coverage reports (Codecov, Coveralls)
  • Documentation for running tests locally
  • Access to our quick-start template for new projects
  • Two weeks of post-release support

Timeline and Cost

Basic setup with unit and integration tests for Node.js or PHP takes 1–2 days. Adding coverage and badge — another half day. Final timeline depends on project complexity (number of services, test types). Cost is discussed individually.

Order CI pipeline setup from our engineers — we guarantee a stable pipeline and documentation. Get a consultation on implementation — contact us to discuss your project.