{ pkgs, extraModules, turtle, vhack, ... }: vhack.runTest { name = "atuin-sync"; serverDomains = [ { server = "atuin-sync.server"; } ]; nodes = let atuinSession = "01969ec6b8d07e30a9d2df0911fbfe2a"; atuin = turtle.packages."${pkgs.stdenv.hostPlatform.system}".default; in { server = {config, ...}: { imports = extraModules ++ [ ../../../../modules ]; vhack = { persist.enable = true; nginx.enable = true; atuin-sync = { enable = true; fqdn = "atuin-sync.server"; }; }; }; client1 = {config, ...}: { environment.sessionVariables.ATUIN_SESSION = atuinSession; environment.systemPackages = [ atuin pkgs.sqlite-interactive ]; }; client2 = {config, ...}: { environment.sessionVariables.ATUIN_SESSION = atuinSession; environment.systemPackages = [ atuin pkgs.sqlite-interactive ]; }; }; services = [ {server = "turtle.service";} ]; testScript = {nodes, ...}: let mkSyncConfig = pkgs.writeShellScript "register-atuin-sync-account" '' mkdir --parents ~/.config/turtle/ cat << EOF > ~/.config/turtle/config.toml [sync] address = "https://atuin-sync.server" user_id_path = "${pkgs.writeText "user-id" "019eb88a-6b51-7e52-b12c-7d30bd8e5928"}" encryption_key_path = "${pkgs.writeText "encryption-key" "3AAgbWsDzL7M00/Mq0LMjsyOCy3MnsypBsyQzKbMywNGzNnMrUBozIINAxdbIiDMhQ=="}" EOF ''; runCommandAndRecordInTurtle = 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="$(turtle history start -- "$escaped_command")" "$@" status=$? turtle history end --exit $status "$id" return $status } # SPDX-SnippetEnd run_and_record_in_atuin "$@" ''; in # Python '' 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}") with subtest("Start turtle daemon"): for client in [client1, client2]: client.succeed("systemd-run turtle-daemon start") for client in [client1, client2]: client.wait_until_succeeds("turtle daemon status") with subtest("Can generate shell history"): client1.succeed("${runCommandAndRecordInTurtle} echo hi - client 1") client2.succeed("${runCommandAndRecordInTurtle} echo hi - client 2") with subtest("Can sync"): for client in [client1, client2]: client.succeed("turtle sync perform") client1.succeed("turtle sync perform") with subtest("Have correct tasks"): hist1 = client1.succeed("turtle history list --cmd-only").strip().split('\n') hist2 = client2.succeed("turtle history list --cmd-only").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}'" with subtest("Can sync again"): client1.succeed("${runCommandAndRecordInTurtle} echo second try - client 1") client2.succeed("${runCommandAndRecordInTurtle} echo second try - client 2") for client in [client1, client2]: client.succeed("turtle sync perform") client1.succeed("turtle sync perform") hist1 = client1.succeed("turtle history list --cmd-only").strip().split('\n') hist2 = client2.succeed("turtle history list --cmd-only").strip().split('\n') hist1.sort() hist2.sort() canonicalHistory = [ # The old history "echo hi - client 1", "echo hi - client 2", # Our newly added history entries "echo second try - client 1", "echo second try - 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, got: '{hist1}', expected: '{canonicalHistory}'" ''; }