Skip to content

Commit

Permalink
Add Nix development setup (#1156)
Browse files Browse the repository at this point in the history
I'm loathe to be the guy who comes in and messes with the development
environment as the first thing he does, but here I am being that guy. 😅

I've been pretty into Nix for my development environments for the past
couple of years for its ability to lock the full set of dev dependencies
in a consistent way across machines and operating systems.

I'll use this setup myself either way, but it's a bit less overhead for
me if I'm able to check in the configs vs dancing around local
gitignores to keep it working. Plus it gives other people the
opportunity to use it!

I tried to document everything nicely, keep it off to the side, and make
it minimally invasive. But I totally understand if you'd rather keep
this out of the repo! Just let me know. 🙇🏻

----

Commit message:

> This setup works well for me, and should allow anybody familiar with
Nix to get up and running with the project really quickly.
> 
> I documented this as an advanced development setup in the same vein as
Docker, leaving the main README instructions as the happy path.
> 
> At any point this can be safely ripped out by reverting this commit or
by manually doing the following:
> 
>  1. remove .envrc, flake.nix, flake.lock, and NIX.md
>  2. clear the the extra entry in .gitignore.
>  3. remove the extra configurable in application_system_test_case.rb
  • Loading branch information
phinze authored Oct 13, 2023
1 parent c3c1f99 commit 167e650
Show file tree
Hide file tree
Showing 8 changed files with 314 additions and 2 deletions.
13 changes: 13 additions & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#
# This file tells direnv, if both it and Nix are installed, to automatically
# load the Nix dependencies defined in flake.nix.
#
# For details on the Nix development setup, see NIX.md.
#
if has nix; then
if ! has nix_direnv_version || ! nix_direnv_version 2.3.0; then
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.3.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8="
fi
nix_direnv_watch_file .ruby-version
use flake
fi
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,7 @@ yarn-debug.log*
gallery-dl
/app/assets/builds/*
!/app/assets/builds/.keep


# The nix development setup puts gems here
/vendor/bundle
5 changes: 5 additions & 0 deletions DOCKER.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Development setup using Docker

> [!WARNING]
> This is meant for advanced users already familiar with Docker. If you're
> looking for general development instructions, please see
> [README.md](README.md).
## Initial setup
The following commands should just be run for the initial setup only. Rebuilding
the docker images is only necessary when upgrading, if there are changes to the
Expand Down
89 changes: 89 additions & 0 deletions NIX.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Development Setup using Nix

> [!WARNING]
> This is meant for advanced users already familiar with Nix. If you're looking
> for general development instructions, please see [README.md](README.md).
## Prerequisites

- [Nix](https://nixos.org/download)
- [Docker w/ Compose](https://github.com/docker/compose#where-to-get-docker-compose) via Docker Desktop or equivalent - this setup runs Rails directly but uses a container for the database.
- [direnv](https://github.com/direnv/direnv) - technically optional but helpful to get the environment to automatically load when entering the project directory

## Initial Dependencies

If you have direnv, the `.envrc` file in the repository will get everything set
up for you automatically, you just need to run `direnv allow`. If you're not
using direnv, you can manually start a development shell with `nix develop`.

## Database

This setup uses the development database configured in `docker-compose.yml`,
which can be started like this:

```shell-session
$ docker compose up -d database
```

The database is working properly if this command produces a list of databases:

```shell-session
$ psql -l "$DATABASE_URL"
```

## Bootstrapping

Use the `setup` script to get started for the first time.

```shell-session
$ bin/setup
```

This script will:

- Fetch Ruby and NPM dependencies
- Bootstrap the development database
- Load some sample data into the development database

The setup script doesn't create the test database, so do that separately:

```shell-session
$ bin/rails db:create:all
```

## Asset Compilation

You can get the assets automatically compiling on file changes by leaving this
command running in a shell:

```shell-session
$ bin/dev -m all=1,web=0
```

Note this skips the Rails server, which we run separately below. This is
because something is preventing Rails from loading properly within the Foreman
environment. If somebody figures this out update this guide!

## Development Server

Run the Rails server in a separate shell:

```shell-session
$ bin/rails server
```

## Running Tests

All tests should be able to run normally:

```shell-session
# Unit tests
$ bin/rails test
# Selenium tests
$ bin/rails test:system
```

The Selenium tests are run by having Nix install Chromium and ChromeDriver and
set a `SELENIUM_CHROME_BINARY` environment variable to point Selenium at
Chromium in `test/application_system_test_case.rb`.
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,6 @@ The following third party services are used:

Once you've completed the setup below, you can login to the app using `admin@example.com` and `password` to see the admin interface.

We generally advise folks to avoid Docker for local development unless it is something thet are already very comfortable with. See [DOCKER.md](DOCKER.md) for instructions on setting up your environment using Docker. For non-Docker installations, follow the instructions below.

### Setting up Circulate on your machine

If you're new to Ruby or Rails applications, a recommended way to get set up is to use the [GoRails setup guide](https://gorails.com/setup). On that page you can select your operating system and the versions of Ruby and Rails you want to setup. It's worth going through the entire tutorial if you haven't worked on a Ruby on Rails application on your computer already as it is easier to sort through possible issues before getting into a large project like Circulate. It will take about 30 minutes to complete this tutorial.
Expand Down Expand Up @@ -235,6 +233,13 @@ the second seed library, Denver Tool Library, by appending `.denver` to the user

All of the seed user passwords are the word "password".

### Alternative Development Setups

We generally advise you to _avoid_ these alternative development setups unless you are already very comfortable with them. The above development instructions should be better for most users.

* **Docker:**: See [DOCKER.md](DOCKER.md) for instructions on setting up your environment using Docker.
* **Nix:** See [NIX.md](NIX.md) for details on installing dependencies with Nix.

## Deployment

Circulate is currently running on Heroku in production, but it should run fairly well anywhere Rails applications can be run.
Expand Down
133 changes: 133 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

57 changes: 57 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#
# This file defines dependencies for the Nix development environment.
#
# For details on the Nix development setup, see NIX.md.
#
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.05";
nixpkgs-ruby.url = "github:bobvanderlinden/nixpkgs-ruby";
nixpkgs-ruby.inputs.nixpkgs.follows = "nixpkgs";
flake-utils.url = "github:numtide/flake-utils";
};

outputs = { self, nixpkgs, nixpkgs-ruby, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system};
# Install a Ruby version matching .ruby-version
ruby = nixpkgs-ruby.lib.packageFromRubyVersionFile {
file = ./.ruby-version;
inherit system;
};
in
{
devShell = with pkgs;
mkShell {
buildInputs = [
ruby
yarn
foreman

# needed to build pg gem, even though we'll run the db from Docker
postgresql

# lib/certificate/generator.rb shells out to convert
imagemagick

# for selenium tests
chromium
chromedriver
];

# Keep gems installed in a subdirectory
BUNDLE_PATH = "./vendor/bundle";

# Point to Docker-hosted db server, using the same settings as
# config/docker.env
DATABASE_URL = "postgres://localhost:5435";
PGUSER = "postgres";

# We'll run chromium in headless mode
HEADLESS = "true";
PARALLEL_WORKERS = "3";
SELENIUM_CHROME_BINARY = "${pkgs.chromium}/bin/chromium";
};
});
}
6 changes: 6 additions & 0 deletions test/application_system_test_case.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@
opts.add_argument "--disable-gpu"
opts.add_argument "--disable-dev-shm-usage"
opts.add_argument "--window-size=1400x1800"

# This configurable is used in the Nix development set up, see NIX.md.
# It's safe to remove if the Nix pieces are ever ripped out.
if ENV.has_key?("SELENIUM_CHROME_BINARY")
opts.binary = ENV["SELENIUM_CHROME_BINARY"]
end
end
)
end
Expand Down

0 comments on commit 167e650

Please sign in to comment.