Supercharge your CI with Snapshot Runners

12 September 20248 minute read

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:

WorkflowGitHub TimeSnapshot Runner Time
Pocketbase Build7 to 8 minutes3m19s (includes 1m1s snapshot creation)
Supabase Playwright Tests5m25s4m56s (includes 1 minute of snapshot creation)
Flux Build and Test20m23s14m28s

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.

Previous post

Ubicloud vs WarpBuild Comparison

22 August 2024
GitHubGithub Actions Runners
Next post

Cost comparison: GitHub Actions Runner Controller (ARC) and WarpBuild

18 September 2024
Actions Runner ControllerARCBYOCGitHub