{ nixos-lib, pkgsUnstable, nixpkgs-unstable, vhackPackages, pkgs, extraModules, nixLib, ... }: nixos-lib.runTest { hostPkgs = pkgs; name = "atuin-sync"; node = { specialArgs = {inherit pkgsUnstable vhackPackages nixpkgs-unstable nixLib;}; # Use the nixpkgs as constructed by the `nixpkgs.*` options pkgs = null; }; nodes = let atuinSession = "01969ec6b8d07e30a9d2df0911fbfe2a"; in { acme = { imports = [ ../../../common/acme/server.nix ../../../common/dns/client.nix ]; }; name_server = {nodes, ...}: { imports = extraModules ++ [ ../../../common/acme/client.nix ../../../common/dns/server.nix ]; vhack.dns.zones = { "atuin-sync.server" = { SOA = { nameServer = "ns"; adminEmail = "admin@server.com"; serial = 2025012301; }; useOrigin = false; A = [ nodes.server.networking.primaryIPAddress ]; AAAA = [ nodes.server.networking.primaryIPv6Address ]; }; }; }; server = {config, ...}: { imports = extraModules ++ [ ../../../../modules ../../../common/acme/client.nix ../../../common/dns/client.nix ]; vhack = { persist.enable = true; nginx.enable = true; atuin-sync = { enable = true; fqdn = "atuin-sync.server"; }; }; }; client1 = {config, ...}: { imports = [ ../../../common/acme/client.nix ../../../common/dns/client.nix ]; environment.sessionVariables.ATUIN_SESSION = atuinSession; environment.systemPackages = [ pkgs.atuin pkgs.sqlite-interactive ]; }; client2 = {config, ...}: { imports = [ ../../../common/acme/client.nix ../../../common/dns/client.nix ]; environment.sessionVariables.ATUIN_SESSION = atuinSession; environment.systemPackages = [ pkgs.atuin pkgs.sqlite-interactive ]; }; }; testScript = {nodes, ...}: let syncLogin = pkgs.writeShellScript "login-atuin-sync-account" '' atuin login --username syncy --password password1234 --key "$1" ''; syncRegister = pkgs.writeShellScript "register-atuin-sync-account" '' atuin register --username syncy --email syncy@email.com --password password1234 ''; mkSyncConfig = pkgs.writeShellScript "register-atuin-sync-account" '' mkdir --parents ~/.config/atuin/ cat << EOF > ~/.config/atuin/config.toml sync_address = "https://atuin-sync.server" # Use the v2 sync [sync] records = true EOF ''; runCommandAndRecordInAtuin = pkgs.writeShellScript "run-command-and-record-in-atuin" '' # SPDX-SnippetBegin # SPDX-SnippetCopyrightText: 2023 mentalisttraceur (https://github.com/mentalisttraceur) # Source: https://github.com/atuinsh/atuin/issues/1188#issuecomment-1698354107 run_and_record_in_atuin() { local id local status local escaped_command="$(printf '%q ' "$@")" id="$(atuin history start -- "$escaped_command")" "$@" status=$? atuin history end --exit $status "$id" return $status } # SPDX-SnippetEnd run_and_record_in_atuin "$@" ''; acme_scripts = import ../../../common/acme/scripts.nix {inherit pkgs;}; in /* python */ '' # Start dependencies for the other services acme.start() acme.wait_for_unit("pebble.service") name_server.start() name_server.wait_for_unit("nsd.service") # Start actual test start_all() with subtest("Add pebble ca key to all services"): for node in [name_server, server, client1, client2]: node.wait_for_unit("network-online.target") node.succeed("${acme_scripts.add_pebble_acme_ca}") server.wait_for_unit("atuin.service") server.wait_for_open_port(443) # Wait for the server to acquire the acme certificate client1.wait_until_succeeds("curl https://atuin-sync.server") with subtest("Setup client syncing"): for client in [client1, client2]: client.succeed("${mkSyncConfig}") client1.succeed("${syncRegister}") for client in [client1, client2]: # See https://docs.atuin.sh/guide/sync/ client.succeed(f"${syncLogin} '{client1.succeed("atuin key")}'") with subtest("Can import shell history"): client1.succeed("${runCommandAndRecordInAtuin} echo hi - client 1") client2.succeed("${runCommandAndRecordInAtuin} echo hi - client 2") with subtest("Can sync tasks"): for client in [client1, client2]: client.succeed("atuin sync --force") client1.succeed("atuin sync --force") with subtest("Have correct tasks"): hist1 = client1.succeed("atuin history list --session --format '{command}'").strip().split('\n') hist2 = client2.succeed("atuin history list --session --format '{command}'").strip().split('\n') hist1.sort() hist2.sort() canonicalHistory = [ "echo hi - client 1", "echo hi - client 2" ] assert hist1 == hist2, f"The clients don't have the same amount of history items, client1: '{hist1}', client2: '{hist2}'" assert hist1 == canonicalHistory, f"The history is not correct: '{hist1}' vs. '{canonicalHistory}'" ''; }