Fediversity/panel/nix/tests.nix
Valentin Gagarin 7c33e8aaf3 scaffold Django web service
This setup is greatly inspired by the one used for [0], although with
notable modifications, such as:
- a SASS preprocessor and CSS compressor
- more streamlined NixOS integration tests
- cleaned up service configuration
- a few notes on how to do things better in the future

[0]: https://github.com/Nix-Security-WG/nix-security-tracker/

Apart from cloning the Nix setup, there were additional steps:
- Create an empty `src` directory, since the package requires it
- In the development shell, run `django-admin startproject panel src`

Note that while you can already do

```bash
manage migrate
manage runserver
```

the NixOS integration tests will fail, since `settings.py` needs
careful massaging to expose knobs that can be turned from our systemd
wrapper. The required changes are introduced in the next commit to make
them observable.

Noteworthy related work:

- https://github.com/sephii/django.nix

  Rather mature setup with a clean interface, uses Caddy as reverse proxy.

- https://git.dgnum.eu/mdebray/djangonix

  A work-in-progress attempt to capture more moving parts through the
  module system, in particular secrets.

- https://github.com/DavHau/django-nixos

  Out of date and somewhat simplistic, but serves as a reasonable
  example for what can be done

I chose the variant I'm intimately familiar with in order to be able to
pass on knowledge or help with maintenance. But for the future
I strongly recommend picking the good bits from the other
implementations that control complexity in static configuration parts
through Nix expressions.
2025-02-13 00:26:28 +01:00

62 lines
1.9 KiB
Nix

{ lib, pkgs }:
let
# TODO: specify project/service name globally
name = "panel";
defaults = {
services.${name} = {
enable = true;
production = false;
restart = "no";
domain = "example.com";
secrets = {
SECRET_KEY = pkgs.writeText "SECRET_KEY" "secret";
};
};
virtualisation = {
memorySize = 2048;
cores = 2;
};
};
in
lib.mapAttrs (name: test: pkgs.testers.runNixOSTest (test // { inherit name; })) {
application-tests = {
inherit defaults;
nodes.server = _: { imports = [ ./configuration.nix ]; };
# run all application-level tests managed by Django
# https://docs.djangoproject.com/en/5.0/topics/testing/overview/
testScript = ''
server.succeed("manage test")
'';
};
admin = {
inherit defaults;
nodes.server = _: { imports = [ ./configuration.nix ]; };
# check that the admin interface is served
testScript = ''
server.wait_for_unit("multi-user.target")
server.wait_for_unit("${name}.service")
server.wait_for_open_port(8000)
server.succeed("curl --fail -L -H 'Host: example.org' http://localhost/admin")
'';
};
sass-processing = {
inherit defaults;
nodes.server = _: { imports = [ ./configuration.nix ]; };
extraPythonPackages = ps: with ps; [ beautifulsoup4 ];
skipTypeCheck = true;
# check that stylesheets are pre-processed and served
testScript = ''
from bs4 import BeautifulSoup
server.wait_for_unit("multi-user.target")
server.wait_for_unit("${name}.service")
server.wait_for_open_port(8000)
stdout = server.succeed("curl --fail -H 'Host: example.org' http://localhost")
# the CSS is auto-generated with a hash in the file name
html = BeautifulSoup(stdout, 'html.parser')
css = html.find('link', type="text/css")['href']
server.succeed(f"curl --fail -H 'Host: example.org' http://localhost/{css}")
'';
};
}