Merge pull request #207646 from Enzime/vsce/test-remote-ssh

authored by Sandro and committed by GitHub 60d31a2a 39b3edb1

+194 -26
+1
nixos/tests/all-tests.nix
··· 814 814 victoriametrics = handleTest ./victoriametrics.nix {}; 815 815 vikunja = handleTest ./vikunja.nix {}; 816 816 virtualbox = handleTestOn ["x86_64-linux"] ./virtualbox.nix {}; 817 + vscode-remote-ssh = handleTestOn ["x86_64-linux"] ./vscode-remote-ssh.nix {}; 817 818 vscodium = discoverTests (import ./vscodium.nix); 818 819 vsftpd = handleTest ./vsftpd.nix {}; 819 820 warzone2100 = handleTest ./warzone2100.nix {};
+124
nixos/tests/vscode-remote-ssh.nix
··· 1 + import ./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; 15 + in { 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 + })
+27 -20
pkgs/applications/editors/vscode/extensions/ms-vscode-remote.remote-ssh/default.nix
··· 1 1 { lib 2 + , nixosTests 2 3 , vscode-utils 3 4 , useLocalExtensions ? false 4 5 }: ··· 8 9 9 10 let 10 11 inherit (vscode-utils) buildVscodeMarketplaceExtension; 11 - 12 - nodeVersion = "16"; 13 12 14 13 # As VS Code executes this code on the remote machine 15 14 # we test to see if we can build Node from Nixpkgs ··· 23 22 serverNode="$serverDir/node" 24 23 echo "VS Code Node: $serverNode" 25 24 26 - # Check if VS Code Server has a non-working Node or the wrong version of Node 27 - if ! nodeVersion=$($serverNode -v) || [ "\''${nodeVersion:1:2}" != "${nodeVersion}" ]; then 25 + # Check if Node included with VS Code Server runs 26 + if ! nodeVersion=$($serverNode -v); then 28 27 echo "VS Code Node Version: $nodeVersion" 29 28 30 - if nix-build "<nixpkgs>" -A nodejs-${nodeVersion}_x --out-link "$serverDir/nix" && [ -e "$serverDir/nix/bin/node" ]; then 31 - nodePath="$serverDir/nix/bin/node" 29 + if ! nix-build "<nixpkgs>" -A patchelf --out-link "$serverDir/patchelf" || ! "$serverDir/patchelf/bin/patchelf" --version; then 30 + echo "Failed to get patchelf from nixpkgs" 32 31 fi 33 32 34 - echo "Node from Nix: $nodePath" 33 + if [ -e $serverNode.orig ]; then 34 + cp $serverNode.orig $serverNode 35 + else 36 + cp $serverNode $serverNode.orig 37 + fi 35 38 36 - nodeVersion=$($nodePath -v) 37 - echo "Node from Nix Version: $nodeVersion" 39 + if ! nix-build "<nixpkgs>" -A bintools --out-link $serverDir/bintools; then 40 + echo "Failed to build bintools from nixpkgs" 41 + fi 42 + 43 + INTERPRETER=$(cat $serverDir/bintools/nix-support/dynamic-linker) 44 + 45 + echo "Interpreter from bintools: $INTERPRETER" 38 46 39 - if [ "\''${nodeVersion:1:2}" != "${nodeVersion}" ]; then 40 - echo "Getting Node from Nix failed, use Local Node instead" 41 - nodePath=$(which node) 42 - echo "Local Node: $nodePath" 43 - nodeVersion=$($nodePath -v) 44 - echo "Local Node Version: $nodeVersion" 47 + if ! nix-build "<nixpkgs>" -A stdenv.cc.cc.lib --out-link $serverDir/cc; then 48 + echo "Failed to build stdenv.cc.cc.lib from nixpkgs" 45 49 fi 46 50 47 - if [ "\''${nodeVersion:1:2}" == "${nodeVersion}" ]; then 48 - echo PATCH: replacing $serverNode with $nodePath 49 - ln -sf $nodePath $serverNode 51 + if ! $serverDir/patchelf/bin/patchelf --set-interpreter $INTERPRETER --set-rpath $serverDir/cc-lib/lib $serverNode; then 52 + echo "Failed to patch Node binary" 50 53 fi 54 + 55 + rm "$serverDir/patchelf" 51 56 fi 52 57 53 58 nodeVersion=$($serverNode -v) 54 59 echo "VS Code Node Version: $nodeVersion" 55 60 56 - if [ "\''${nodeVersion:1:2}" != "${nodeVersion}" ]; then 57 - echo "Unsupported VS Code Node version: $nodeVersion", quitting 61 + if ! nodeVersion=$($serverNode -v); then 62 + echo "Unable to fix Node binary, quitting" 58 63 fail_with_exitcode ''${o.InstallExitCode.ServerTransferFailed} 59 64 fi 60 65 ··· 86 91 substituteInPlace "out/extension.js" \ 87 92 --replace '# Start the server\n' '${patch}' 88 93 ''; 94 + 95 + passthru.tests = { inherit (nixosTests) vscode-remote-ssh; }; 89 96 90 97 meta = { 91 98 description = "Use any remote machine with a SSH server as your development environment.";
+4
pkgs/applications/editors/vscode/generic.nix
··· 13 13 , version, src, meta, sourceRoot, commandLineArgs 14 14 , executableName, longName, shortName, pname, updateScript 15 15 , dontFixup ? false 16 + , rev ? null, vscodeServer ? null 17 + 16 18 # sourceExecutableName is the name of the binary in the source archive, over 17 19 # which we have no control 18 20 , sourceExecutableName ? executableName ··· 30 32 inherit executableName longName tests updateScript; 31 33 fhs = fhs {}; 32 34 fhsWithPackages = f: fhs { additionalPkgs = f; }; 35 + } // lib.optionalAttrs (vscodeServer != null) { 36 + inherit rev vscodeServer; 33 37 }; 34 38 35 39 desktopItem = makeDesktopItem {
+15 -2
pkgs/applications/editors/vscode/update-vscode.sh
··· 19 19 VSCODE_VER=$(curl --fail --silent https://api.github.com/repos/Microsoft/vscode/releases/latest | jq --raw-output .tag_name) 20 20 sed -i "s/version = \".*\"/version = \"${VSCODE_VER}\"/" "$ROOT/vscode.nix" 21 21 22 + TEMP_FOLDER=$(mktemp -d) 23 + 22 24 VSCODE_X64_LINUX_URL="https://update.code.visualstudio.com/${VSCODE_VER}/linux-x64/stable" 23 - VSCODE_X64_LINUX_SHA256=$(nix-prefetch-url ${VSCODE_X64_LINUX_URL}) 24 - sed -i "s/x86_64-linux = \".\{52\}\"/x86_64-linux = \"${VSCODE_X64_LINUX_SHA256}\"/" "$ROOT/vscode.nix" 25 + 26 + # Split output by newlines into Bash array 27 + readarray -t VSCODE_X64_LINUX <<< $(nix-prefetch-url --print-path ${VSCODE_X64_LINUX_URL}) 28 + 29 + sed -i "s/x86_64-linux = \".\{52\}\"/x86_64-linux = \"${VSCODE_X64_LINUX[0]}\"/" "$ROOT/vscode.nix" 30 + 31 + tar xf ${VSCODE_X64_LINUX[1]} -C $TEMP_FOLDER 32 + VSCODE_COMMIT=$(jq --raw-output .commit $TEMP_FOLDER/VSCode-linux-x64/resources/app/product.json) 33 + sed -i "s/rev = \".\{40\}\"/rev = \"${VSCODE_COMMIT}\"/" "$ROOT/vscode.nix" 34 + 35 + SERVER_X64_LINUX_URL="https://update.code.visualstudio.com/commit:${VSCODE_COMMIT}/server-linux-x64/stable" 36 + SERVER_X64_LINUX_SHA256=$(nix-prefetch-url ${SERVER_X64_LINUX_URL}) 37 + sed -i "s/sha256 = \".\{51,52\}\"/sha256 = \"${SERVER_X64_LINUX_SHA256}\"/" "$ROOT/vscode.nix" 25 38 26 39 VSCODE_X64_DARWIN_URL="https://update.code.visualstudio.com/${VSCODE_VER}/darwin/stable" 27 40 VSCODE_X64_DARWIN_SHA256=$(nix-prefetch-url ${VSCODE_X64_DARWIN_URL})
+22 -2
pkgs/applications/editors/vscode/vscode.nix
··· 1 - { stdenv, lib, callPackage, fetchurl 1 + { stdenv 2 + , lib 3 + , callPackage 4 + , fetchurl 5 + , nixosTests 6 + , srcOnly 2 7 , isInsiders ? false 3 8 , commandLineArgs ? "" 4 9 , useVSCodeRipgrep ? stdenv.isDarwin ··· 32 37 version = "1.79.1"; 33 38 pname = "vscode"; 34 39 40 + # This is used for VS Code - Remote SSH test 41 + rev = "b380da4ef1ee00e224a15c1d4d9793e27c2b6302"; 42 + 35 43 executableName = "code" + lib.optionalString isInsiders "-insiders"; 36 44 longName = "Visual Studio Code" + lib.optionalString isInsiders " - Insiders"; 37 45 shortName = "Code" + lib.optionalString isInsiders " - Insiders"; ··· 48 56 49 57 sourceRoot = ""; 50 58 59 + # As tests run without networking, we need to download this for the Remote SSH server 60 + vscodeServer = srcOnly { 61 + name = "vscode-server-${rev}.tar.gz"; 62 + src = fetchurl { 63 + name = "vscode-server-${rev}.tar.gz"; 64 + url = "https://update.code.visualstudio.com/commit:${rev}/server-linux-x64/stable"; 65 + sha256 = "0732wpl4fjknhn423k23zrcqz9psjj1iy8lqa0fc8970n1m7i58b"; 66 + }; 67 + }; 68 + 69 + tests = { inherit (nixosTests) vscode-remote-ssh; }; 70 + 51 71 updateScript = ./update-vscode.sh; 52 72 53 73 # Editing the `code` binary within the app bundle causes the bundle's signature ··· 71 91 homepage = "https://code.visualstudio.com/"; 72 92 downloadPage = "https://code.visualstudio.com/Updates"; 73 93 license = licenses.unfree; 74 - maintainers = with maintainers; [ eadwu synthetica maxeaubrey bobby285271 ]; 94 + maintainers = with maintainers; [ eadwu synthetica maxeaubrey bobby285271 Enzime ]; 75 95 platforms = [ "x86_64-linux" "x86_64-darwin" "aarch64-darwin" "aarch64-linux" "armv7l-linux" ]; 76 96 }; 77 97 }
+1 -2
pkgs/build-support/src-only/default.nix
··· 1 1 { stdenv }: 2 2 # srcOnly is a utility builder that only fetches and unpacks the given `src`, 3 - # maybe pathings it in the process with the optional `patches` and 4 - # `buildInputs` attributes. 3 + # and optionally patching with `patches` or adding build inputs. 5 4 # 6 5 # It can be invoked directly, or be used to wrap an existing derivation. Eg: 7 6 #