Skip to content

Integration Tests ​

Every stack in this repository ships a NixOS VM integration test that deploys the stack like a real installation and waits for all of its containers to reach a stable active (running) state. The scaffolding behind those tests is exported as the lib flake output, so you can run the same kind of test against your own configuration.

nix
{
  inputs.nix-podman-stacks.url = "github:Tarow/nix-podman-stacks";

  outputs = { nixpkgs, nix-podman-stacks, ... }: let
    system = "x86_64-linux";
    pkgs = nixpkgs.legacyPackages.${system};
  in {
    integrationTests.${system}.myhost = nix-podman-stacks.lib.mkIntegrationTest {
      inherit pkgs;
      name = "myhost-integration";
      modules = [./stacks.nix];
    };
  };
}

Run it with:

sh
nix build .#integrationTests.x86_64-linux.myhost --option sandbox false

WARNING

The VM needs network access, so the Nix sandbox has to be disabled with --option sandbox false. Tests are Linux-only and take a few minutes each, since the containers are pulled inside the VM.

What the flake exports ​

OutputPurpose
mkIntegrationTestBuilds the VM test from a list of Home Manager modules
stackTestModulesThe stack test modules of this repository, e.g. stackTestModules.authelia

Options of mkIntegrationTest ​

OptionTypeDefaultDescription
pkgsattrsetrequirednixpkgs.legacyPackages.<system> of a Linux system
namestring"nps-integration"Test name, also used as derivation name
moduleslist[]Home Manager modules for the test user
extraSpecialArgsattrset{}Extra module arguments for the test user
extraNixosModuleslist[]Extra NixOS modules, imported after the base
expectedUnitsnull | list of strnullnull derives them from the containers, [] skips the check
extraExpectedUnitslist of str[]Appended to the unit list
extraTestScriptstring""Python run after the unit check passed
testScriptnull | stringnullReplaces the driver, including the unit check
memorySizenull | intnullVM RAM in MiB. null uses npsTests.memorySize (2048)
diskSizeint8192VM disk size in MiB
waitTimeoutint600Seconds all units share to become active, not per unit
stabilityGraceint60Seconds a running unit must stay up without restarting
globalTimeoutnull | intnullDriver timeout, derived from the two timeouts when null

Your own test ​

mkIntegrationTest activates the given modules for a throwaway ci user and verifies that every container comes up and stays up. Pass your config, then a module for whatever you want to check differently:

nix
integrationTests.${system}.microbin = nix-podman-stacks.lib.mkIntegrationTest {
  inherit pkgs;
  name = "microbin-integration";
  modules = [
    ({lib, dummySecretFile, ...}: {
      nps.stacks.microbin = {
        enable = true;
        # test an older build than the pinned default
        containers.microbin.image = lib.mkForce "ghcr.io/danielszabo99/microbin:v2.1.4";
        extraEnv = {
          MICROBIN_ADMIN_USERNAME = "admin";
          MICROBIN_ADMIN_PASSWORD.fromFile = dummySecretFile;
          MICROBIN_UPLOADER_PASSWORD.fromFile = dummySecretFile;
        };
      };
    })
  ];
  extraTestScript = ''
    machine.wait_for_open_port(8080)
  '';
};

Secrets are yours to provide, via sops-nix, agenix or pkgs.writeText, or you can use the inert dummy* arguments the test user already gets: dummySecretFile, dummyClientSecretHash, dummyUser, dummyEmail. Anything the helper sets can be overridden with lib.mkForce in one of your own modules, for example the domain Traefik and the OIDC URLs derive from:

nix
({lib, ...}: {
  nps.stacks.traefik.domain = lib.mkForce "my.example";
})

A memory hungry stack raises npsTests.memorySize in its own test module.

Combining with the bundled test modules ​

stackTestModules contains the test module of every stack in this repository, so an OIDC deployment can reuse the Traefik and Authelia setup instead of rebuilding it. Pick a stack whose OIDC is configured declaratively: oidc.enable = true writes the app's own provider config, while oidc.registerClient = true (e.g. memos) only registers the client in Authelia and leaves the rest to the app's web UI.

nix
modules = [
  # brings Traefik with a self-signed cert, plus lldap
  nix-podman-stacks.lib.stackTestModules.authelia
  ({dummyClientSecretHash, dummyEmail, dummySecretFile, dummyUser, ...}: {
    nps.stacks.paperless = {
      enable = true;
      adminProvisioning = {
        username = dummyUser;
        email = dummyEmail;
        passwordFile = dummySecretFile;
      };
      oidc = {
        enable = true;
        clientSecretFile = dummySecretFile;
        clientSecretHash = dummyClientSecretHash;
      };
      secretKeyFile = dummySecretFile;
      db.passwordFile = dummySecretFile;
      extraEnv.PAPERLESS_OCR_LANGUAGES = "eng deu";
    };
  })
];