Why Local Builds and Tests Are Faster than CI
Developers often experience faster builds locally compared to their CI systems, largely because their local machine has cached dependencies, libraries, and other artifacts. Every CI runner starts fresh, losing this advantage. This disparity in build times can cause frustration and delay continuous integration and deployment workflows.
Caching in CI Runners
CI builds can be sped up by caching dependencies, Docker layers, and other artifacts. However, traditional CI caching mechanisms can't fully replicate the performance of local builds due to the limitations of what can be cached.
Enter Snapshot Runners
Snapshot Runners offer a more powerful caching approach. Instead of relying on external caches, Snapshot Runners capture a complete snapshot of the VM runner just before it exits. This snapshot includes all dependencies, build caches, and system-level optimizations, allowing subsequent runners to start with a fully primed environment. This drastically reduces initialization time and improves overall build performance.
Seamlessly Integrate Snapshot Runners into Your CI Pipelines
Integrating Snapshot Runners into your existing workflows is easy. Simply change the warp runner in runs-on
to have a snapshot.key
parameter. This key is used to identify the snapshot and load it into the runner.
1- runs-on: "warp-ubuntu-latest-x64-4x"
2+ runs-on: "warp-ubuntu-latest-x64-4x;snapshot.key=pocketbase-snp-warp"
Also, add the WarpBuilds/snapshot-save@v1
action at the end of your workflow or at the point where you want to create the snapshot.
It is recommended to clean up all credentials and sensitive information before creating a snapshot.
Here's an example workflow which we modified to use snapshot runners. This is the basebuild action for Pocketbase, a popular open-source project.
1name: basebuild
2
3on:
4 pull_request:
5 push:
6
7jobs:
8 goreleaser:
9 runs-on: "warp-ubuntu-latest-x64-4x;snapshot.key=pocketbase-snp-warp"
10
11 steps:
12 - name: Checkout
13 uses: actions/checkout@v4
14 with:
15 fetch-depth: 0
16
17 - name: Log GitHub context
18 uses: actions/github-script@v7
19 with:
20 script: |
21 console.log('GitHub context:', context);
22 core.debug('Full GitHub context object:');
23 core.debug(JSON.stringify(context, null, 2));
24
25 - name: Set up Node.js
26 uses: WarpBuilds/setup-node@v4
27 with:
28 node-version: 20.11.0
29
30 - name: Ensure GCC is installed
31 run: |
32 if ! command -v gcc &> /dev/null
33 then
34 echo "GCC could not be found, installing..."
35 sudo apt-get update
36 sudo apt-get install -y gcc
37 else
38 echo "GCC is already installed"
39 fi
40
41 - name: Set up Go
42 uses: WarpBuilds/setup-go@v5
43 with:
44 go-version: ">=1.22.5"
45 cache: false
46
47 - name: Build Admin dashboard UI
48 run: npm --prefix=./ui ci && npm --prefix=./ui run build
49
50 - name: Run tests
51 run: go test ./...
52
53 - name: Run GoReleaser
54 uses: goreleaser/goreleaser-action@v3
55 with:
56 distribution: goreleaser
57 version: latest
58 args: release --clean
59 env:
60 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
61
62 - name: Create snapshot
63 if: github.event_name == 'push'
64 uses: WarpBuilds/snapshot-save@v1
65 with:
66 wait-timeout-minutes: 30
67 fail-on-error: "false"
68 alias: "pocketbase-snp-warp"
Benchmarks
We modified some popular CI workflows to use Snapshot Runners. Here are the results:
Workflow | GitHub Time | Snapshot Runner Time |
---|---|---|
Pocketbase Build | 7 to 8 minutes | 3m19s (includes 1m1s snapshot creation) |
Supabase Playwright Tests | 5m25s | 4m56s (includes 1 minute of snapshot creation) |
Flux Build and Test | 20m23s | 14m28s |
Common Pitfalls and Best Practices
Network attached disks
Currently, snapshot runners use a network attached disk which might perform worse than Warpbuild's cache action in case of large number of files. For large directories like node_modules, it may be better to use cache action instead of relying on files in snapshot. Combine both of these approaches based on your use case.
Refreshing Snapshots
While Snapshot Runners can store everything from previous builds, it is a good idea to refresh the base snapshot periodically to prevent outdated or unnecessary artifacts from accumulating. The snapshot can be refreshed by using the snapshot-save
action with the same key.
Runner Compatibility
Snapshot runners are a WarpBuild exclusive feature and works only with WarpBuild Runners. Get Started with WarpBuild.