Skip to content

Commit

Permalink
release: v0.0.5: async and integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
hraban committed Jan 8, 2025
1 parent b9259ce commit 807cb70
Show file tree
Hide file tree
Showing 22 changed files with 1,334 additions and 840 deletions.
2 changes: 2 additions & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# ruff format
706580fbb393467063c6a372a902172203bfd382
23 changes: 18 additions & 5 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ on:
pull_request:
push:

name: Syntax
name: CI
jobs:
nocommit:
runs-on: ubuntu-latest
Expand All @@ -11,13 +11,26 @@ jobs:
- name: "nocommit checker"
uses: nobssoftware/nocommit@v2

check:
nix-flake-check:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Nix
uses: DeterminateSystems/nix-installer-action@v9
- uses: cachix/install-nix-action@v30
with:
enable_kvm: true
extra_nix_config: "system-features = nixos-test benchmark big-parallel kvm"
- name: Configure Nix cache
uses: DeterminateSystems/magic-nix-cache-action@main
- run: nix flake check
- run: nix flake check -L

# Ensure nix flake show isn’t broken
nix-flake-show:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Nix
uses: DeterminateSystems/nix-installer-action@v9
# No need for a cache
- run: nix flake show
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,20 @@ Highlights:
from brrr import task

@task
def fib(n: int, salt=None):
async def fib(n: int, salt=None):
match n:
case 0: return 0
case 1: return 1
case _: return sum(fib.map([[n - 2, salt], [n - 1, salt]]))
case _: return sum(await fib.map([[n - 2, salt], [n - 1, salt]]))

@task
def fib_and_print(n: str):
f = fib(int(n))
async def fib_and_print(n: str):
f = await fib(int(n))
print(f"fib({n}) = {f}", flush=True)
return f

@task
def hello(greetee: str):
async def hello(greetee: str):
greeting = f"Hello, {greetee}!"
print(greeting, flush=True)
return greeting
Expand Down
52 changes: 52 additions & 0 deletions brrr-demo.module.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Copyright © 2024 Brrr Authors
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, version 3 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

# A NixOS module for a brrr demo binary. N.B.: It does not contain any
# dependencies; this is just the demo script.
#
# Inspired by
# https://blakesmith.me/2024/03/02/running-nixos-tests-with-flakes.html

{ lib, config, pkgs, ... }: {
options.services.brrr-demo = let
native = import ./brrr-demo.options.nix { inherit lib pkgs; };
mod1 = { options = native; };
mod2 = {
options.enable = lib.mkEnableOption "brrr-demo";
};
in lib.mkOption {
description = "Brrr demo service configuration";
type = lib.types.submoduleWith {
modules = [ mod1 mod2 ];
};
default = {};
};

config = let
cfg = config.services.brrr-demo;
in lib.mkIf cfg.enable {

systemd.services.brrr-demo = {
inherit (cfg) environment;
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
script = ''
exec ${lib.getExe cfg.package} ${lib.escapeShellArgs cfg.args}
'';
serviceConfig = {
Type = "simple";
};
};
};
}
43 changes: 43 additions & 0 deletions brrr-demo.options.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Copyright © 2024 Brrr Authors
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, version 3 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

# Module options for any brrr-demo service. These are shared between the actual
# NixOS module and the services-flake module. N.B.: pkgs must have a brrr-demo
# derivation available, from an overlay.
#
# I think I’m still missing one layer of submodule use here--these are just the
# raw options for the caller to directly import, but I’m sure there’s some way
# to use submodule for this instead? Maybe... deferred? This works for now but
# TBD.

{ lib, pkgs }:

with lib.types; {
# You’ll want to override this unless you use an overlay
package = lib.mkPackageOption pkgs "brrr-demo" { };
args = lib.mkOption {
default = [];
type = listOf str;
};
environment = lib.mkOption {
type = types.attrsOf types.str;
default = { };
example = {
AWS_ENDPOINT_URL = "http://localhost:12345";
};
description = ''
Extra environment variables passed to the `brrr-demo` process.
'';
};
}
20 changes: 2 additions & 18 deletions brrr-demo.service.nix
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,8 @@
# Ok.

{ config, pkgs, name, lib, ... }: {
options = with lib.types; {
# You’ll want to override this unless you use an overlay
package = lib.mkPackageOption pkgs "brrr-demo" { };
args = lib.mkOption {
default = [];
type = listOf str;
};
environment = lib.mkOption {
type = types.attrsOf types.str;
default = { };
example = {
AWS_ENDPOINT_URL = "http://localhost:12345";
};
description = ''
Extra environment variables passed to the `brrr-demo` process.
'';
};
};
# services-flake requires setting the options top-level
options = import ./brrr-demo.options.nix { inherit lib pkgs; };
config = {
outputs.settings.processes.${name} = {
environment = config.environment;
Expand Down
114 changes: 114 additions & 0 deletions brrr-demo.test.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Copyright © 2024 Brrr Authors
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, version 3 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

# Inspired by
# https://blakesmith.me/2024/03/02/running-nixos-tests-with-flakes.html

{ self, pkgs }:

# Distributed test across multiple VMs, so there’s still some room for bugs to
# creep into the actual demo. Both are nice to have so we should probably add a
# test that replicates the actual demo as closely as possible to catch any
# errors there.
pkgs.testers.runNixOSTest {
name = "brrr-test";

nodes.datastores = { config, pkgs, ... }: {
imports = [
# Not going to export and dogfood this--it’s just local only
./dynamodb.module.nix
];
services.redis.servers.main = {
enable = true;
port = 6379;
openFirewall = true;
bind = null;
logLevel = "debug";
settings.protected-mode = "no";
};
services.dynamodb = {
enable = true;
openFirewall = true;
};
};
nodes.server = { config, pkgs, ... }: {
imports = [
self.nixosModules.brrr-demo
];
networking.firewall.allowedTCPPorts = [ 8080 ];
services.brrr-demo = {
enable = true;
package = self.packages.${pkgs.system}.brrr-demo;
args = [ "server" ];
environment = {
BRRR_DEMO_LISTEN_HOST = "0.0.0.0";
BRRR_DEMO_REDIS_URL = "redis://datastores:6379";
AWS_DEFAULT_REGION = "foo";
AWS_ENDPOINT_URL = "http://datastores:8000";
AWS_ACCESS_KEY_ID = "foo";
AWS_SECRET_ACCESS_KEY = "bar";
};
};
};
nodes.worker = { config, pkgs, ... }: {
imports = [
self.nixosModules.brrr-demo
];
services.brrr-demo = {
enable = true;
package = self.packages.${pkgs.system}.brrr-demo;
args = [ "worker" ];
environment = {
BRRR_DEMO_REDIS_URL = "redis://datastores:6379";
AWS_DEFAULT_REGION = "foo";
AWS_ENDPOINT_URL = "http://datastores:8000";
AWS_ACCESS_KEY_ID = "foo";
AWS_SECRET_ACCESS_KEY = "bar";
};
};
};
# Separate node entirely just for the actual testing
nodes.tester = { config, pkgs, ... }: let
test-script = pkgs.writeShellApplication {
name = "test-brrr-demo";
# 😂
text = ''
eval "$(curl --fail -sSL "http://server:8080/hello?greetee=Jim" | jq '. == {status: "ok", result: "Hello, Jim!"}')"
eval "$(curl --fail -sSL "http://server:8080/fib_and_print?n=6&salt=abcd" | jq '. == {status: "ok", result: 8}')"
'';
};
in {
environment.systemPackages = [
test-script
] ++ (with pkgs; [
curl
jq
]);
};

globalTimeout = 2 * 60;

testScript = ''
# Start first because it's a dependency
datastores.wait_for_unit("default.target")
# Server initializes the stores
server.wait_for_unit("default.target")
worker.wait_for_unit("default.target")
tester.wait_for_unit("default.target")
server.wait_for_open_port(8080)
tester.wait_until_succeeds("curl --fail -sSL -X POST 'http://server:8080/hello?greetee=Jim'")
tester.wait_until_succeeds("curl --fail -sSL -X POST 'http://server:8080/fib_and_print?n=6&salt=abcd'")
tester.wait_until_succeeds("test-brrr-demo")
'';
}
Loading

0 comments on commit 807cb70

Please sign in to comment.