1import ./make-test-python.nix ({ lib, ... }@args: let
2 pkgs = args.pkgs.extend (self: super: {
3 stdenv = super.stdenv.override {
4 config = super.config // {
5 allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
6 "vscode" "vscode-with-extensions" "vscode-extension-ms-vscode-remote-remote-ssh"
7 ];
8 };
9 };
10 });
11
12 inherit (import ./ssh-keys.nix pkgs) snakeOilPrivateKey snakeOilPublicKey;
13
14 inherit (pkgs.vscode.passthru) rev vscodeServer;
15in {
16 name = "vscode-remote-ssh";
17 meta.maintainers = with lib.maintainers; [ Enzime ];
18
19 nodes = let
20 serverAddress = "192.168.0.2";
21 clientAddress = "192.168.0.1";
22 in {
23 server = { ... }: {
24 networking.interfaces.eth1.ipv4.addresses = [ { address = serverAddress; prefixLength = 24; } ];
25 services.openssh.enable = true;
26 users.users.root.openssh.authorizedKeys.keys = [ snakeOilPublicKey ];
27 virtualisation.additionalPaths = with pkgs; [ patchelf bintools stdenv.cc.cc.lib ];
28 };
29 client = { ... }: {
30 imports = [ ./common/x11.nix ./common/user-account.nix ];
31 networking.interfaces.eth1.ipv4.addresses = [ { address = clientAddress; prefixLength = 24; } ];
32 networking.hosts.${serverAddress} = [ "server" ];
33 test-support.displayManager.auto.user = "alice";
34 environment.systemPackages = [
35 (pkgs.vscode-with-extensions.override {
36 vscodeExtensions = [
37 pkgs.vscode-extensions.ms-vscode-remote.remote-ssh
38 ];
39 })
40 ];
41 };
42 };
43
44 enableOCR = true;
45
46 testScript = let
47 jq = "${pkgs.jq}/bin/jq";
48
49 sshConfig = builtins.toFile "ssh.conf" ''
50 UserKnownHostsFile=/dev/null
51 StrictHostKeyChecking=no
52 '';
53
54 vscodeConfig = builtins.toFile "settings.json" ''
55 {
56 "window.zoomLevel": 1,
57 "security.workspace.trust.startupPrompt": "always"
58 }
59 '';
60 in ''
61 def connect_with_remote_ssh(screenshot, should_succeed):
62 print(f"connect_with_remote_ssh({screenshot=}, {should_succeed=})")
63
64 if server.execute("test -d ~/.vscode-server")[0] == 0:
65 server.succeed("rm -r ~/.vscode-server")
66
67 server.succeed("mkdir -p ~/.vscode-server/bin")
68 server.succeed("cp -r ${vscodeServer} ~/.vscode-server/bin/${rev}")
69
70 client.succeed("sudo -u alice code --remote=ssh-remote+root@server /root")
71 client.wait_for_window("Visual Studio Code")
72
73 client.wait_for_text("Do you trust the authors" if should_succeed else "Disconnected from SSH")
74 client.screenshot(screenshot)
75
76 if should_succeed:
77 # Press the Don't Trust button
78 client.send_key("tab")
79 client.send_key("tab")
80 client.send_key("tab")
81 client.send_key("\n")
82 else:
83 # Close the error dialog
84 client.send_key("esc")
85
86 # Don't send Ctrl-q too quickly otherwise it might not get sent to VS Code
87 client.sleep(1)
88 client.send_key("ctrl-q")
89 client.wait_until_fails("pidof code")
90
91
92 start_all()
93 server.wait_for_open_port(22)
94
95 VSCODE_COMMIT = server.execute("${jq} -r .commit ${pkgs.vscode}/lib/vscode/resources/app/product.json")[1].rstrip()
96 SERVER_COMMIT = server.execute("${jq} -r .commit ${vscodeServer}/product.json")[1].rstrip()
97
98 print(f"{VSCODE_COMMIT=} {SERVER_COMMIT=}")
99 assert VSCODE_COMMIT == SERVER_COMMIT, "VSCODE_COMMIT and SERVER_COMMIT do not match"
100
101 client.wait_until_succeeds("ping -c1 server")
102 client.succeed("sudo -u alice mkdir ~alice/.ssh")
103 client.succeed("sudo -u alice install -Dm 600 ${snakeOilPrivateKey} ~alice/.ssh/id_ecdsa")
104 client.succeed("sudo -u alice install ${sshConfig} ~alice/.ssh/config")
105 client.succeed("sudo -u alice install -Dm 644 ${vscodeConfig} ~alice/.config/Code/User/settings.json")
106
107 client.wait_for_x()
108 client.wait_for_file("~alice/.Xauthority")
109 client.succeed("xauth merge ~alice/.Xauthority")
110 # Move the mouse out of the way
111 client.succeed("${pkgs.xdotool}/bin/xdotool mousemove 0 0")
112
113 with subtest("fails to connect when nixpkgs isn't available"):
114 server.fail("nix-build '<nixpkgs>' -A hello")
115 connect_with_remote_ssh(screenshot="no_node_installed", should_succeed=False)
116 server.succeed("test -e ~/.vscode-server/bin/${rev}/node")
117 server.fail("~/.vscode-server/bin/${rev}/node -v")
118
119 with subtest("connects when server can patch Node"):
120 server.succeed("mkdir -p /nix/var/nix/profiles/per-user/root/channels")
121 server.succeed("ln -s ${pkgs.path} /nix/var/nix/profiles/per-user/root/channels/nixos")
122 connect_with_remote_ssh(screenshot="build_node_with_nix", should_succeed=True)
123 '';
124})