Skip to content

A sample app to illustrate a better CI workflow using nix. This example tests a web app in Github Actions and deploys it to Vercel.

Notifications You must be signed in to change notification settings

thenbe/template-nix-ci-vercel

Repository files navigation

template-nix-ci-vercel

This template showcases how to take advantage of nix to smooth out some rough edges when working with CI (Github Actions) and deploying to a cloud provider (Vercel).

Who is this for?

The target audience are those who want to deploy a non-trivial web app to a platform like Vercel (or Cloudflare, Netlify, etc) and have it tested in CI. The primary benefit of this approach is that it lets you avoid having to carefully tiptoe around three different environments: your local machine, the Github Actions runner, and Vercel's build environment.

Features

  • ☮️ Simplifies your CI workflow using nix. (example)
  • 😩 Avoids the dreaded slow feedback loop of debugging CI.
  • 🤹 Avoids having to tiptoe around three different environments (your local dev environment, Github Actions runner, Vercel's build environment) by using a single, locally reproducible one.
  • ♻️ Auto deploys to vercel on push/PR and comments with the URL to the preview deployment using vercel-action.

What

Most of the files in this repo are irrelevant (from the demo sveltekit app created with npm create svelte@latest myapp), so you should only care about the following files:

  • ci.yml: The github action lint and test our app.
  • deploy.yml: The github action to build and deploy our app to vercel.
  • flake.nix: The declarative nix configuration.

Why

While the concept itself reaches further than this specific example, I focus on it from a web dev point of view. Specifically I shed light on how it tames rough edges like:

  • configuring non-trivial tools (playwright in this example) locally vs configuring it in CI
  • using tools that are not available on Vercel's build environment

The problem

To illustrate the issue, let's assume we have a web app that we want to:

  1. Build and test in CI
  2. Deploy from CI

Step 1 (build and test in CI)

For our web app, playwright makes step 1 tricky in CI since it uses real browsers for testing. This does make it a powerful tool for testing, however that comes at the cost of some increased setup complexity as the browsers need to be downloaded before tests can run. This can get hairy in CI.

Configuration: For example, it's not clear to how to best setup playwright in CI when working with pnpm. Specifically, should we use the npx playwright install with the --with-deps flag as instructed by playwright's docs? Or should we set PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 and then run playwright install (without the flag) to download the browsers? What about caching? Do we need a manual workaround for that?

Figuring out the answers to all of those questions is hard enough. Having that magnified by the slow feedback loop of CI is just painful. Even if we're currently familiar with playwright and have figured out the current best approach, we will still need to debug future issues against the same frustratingly slow feedback loop. Essentially, the issue is that we are dealing with an environment that will always be different than our local environment.

Step 2 (deploy from CI)

Admittedly, for simple projects, the best approach to deploy to vercel is to use vercel's pipeline. It requires zero configuration, does what we expect, and stays out of the way -- until it doesn't.

As a rule of thumb, I know I've reached this stage when I need to make changes to my project just to make the build exit successfully in vercel's build environment. For example, assume our app uses a codegen tool that is incompatible with vercel's build environment. Should we concede and begin committing the generated code into git? That would "fix" the immediate issue but would leave us with an entirely different set of problems.

The solution

The nix approach used in this template addresses the previous concerns by making all environments identical. Instead of dealing with three different environments (local, Github Actions runner, Vercel build environment), we now get to work with a single environment that:

  1. Can be debugged locally
  2. Has immediate access to some 80,000 packages (Nixpkgs is the current largest and most up to date package repository in the world)

If it works on your machine, it will work in CI.

Usage

Requirements

About

A sample app to illustrate a better CI workflow using nix. This example tests a web app in Github Actions and deploys it to Vercel.

Resources

Stars

Watchers

Forks