CI/CD Speed: Vitest `--changed` + GH Actions + Bun
Speed up CI/CD with Vitest --changed, GitHub Actions fetch-depth: 0, and Bun Runtime. Run only tests related to changed files and slash CI minutes.
1. The Problem: Why is CI/CD Slow and Costly?#
By default, standard CI runners typically perform two resource-heavy tasks:
- Running the entire test suite: Even if you only change a single line of code in one component file, most traditional CI systems still scan and execute hundreds or thousands of unrelated test cases.
- Shallow checkouts: GitHub Actions defaults to
fetch-depth: 1, meaning it only downloads the absolute latest commit without pulling any Git history. While this makes cloning fast, it leaves tools that need to compare branches (likemainand your current branch) completely “blind.”
2. The Solution: Vitest --changed Meets fetch-depth: 0#
What is Vitest --changed?#
Vitest provides a remarkably powerful flag called --changed. When enabled, Vitest automatically detects which files have been modified compared to a base branch (usually main) and only runs test files directly or indirectly affected by those changes.
The Missing Link: Why fetch-depth: 0 is Required#
Because Vitest relies on Git history to determine file modifications, running a default shallow clone (fetch-depth: 1) leaves Vitest without the history context required to run comparisons against main, resulting in errors or skipped filters.
This is why you must configure actions/checkout with fetch-depth: 0 to fetch the full Git history so Vitest has the data it needs to cross-reference changes.
- uses: actions/checkout@v4
with:
fetch-depth: 0yaml3. Supercharging Speed with Bun Runtime#
Instead of relying on traditional Node.js alongside npm or yarn, integrating Bun across your entire workflow delivers a massive performance boost:
- Installing dependencies (
bun install): Up to 10x to 30x faster than npm. - Running tests (
bun x vitest): Leverages Bun’s hyper-optimized JavaScript and TypeScript execution speed.
4. Complete GitHub Actions Workflow Configuration#
Here is a complete sample workflow file (.github/workflows/ci.yml) bringing all three elements together:
name: CI
on:
pull_request:
branches: [ main ]
push:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Run Vitest on changed files
run: bun x vitest run --changed mainyaml5. Key Benefits#
Implementing this setup in your project unlocks immediate advantages:
- Massive CI time savings: Test execution time for small PRs can drop from minutes down to mere seconds since only relevant test cases run.
- Faster feedback loops: Developers no longer have to wait anxiously to find out if their code passes checks.
- Optimized resource usage: Reduces runner usage time on GitHub Actions, saving costs if you use self-hosted runners or paid minutes.
Conclusion#
Optimizing your CI/CD pipeline doesn’t require overly complex architecture. Sometimes, a smart combination of Vitest’s built-in intelligence (--changed), proper Git history configuration (fetch-depth: 0), and the raw power of Bun runtime is all it takes to completely transform your development workflow.
Try implementing this in your next project and experience the speed difference yourself!