diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 043d8a56d0c63..d625d382a9261 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -555,6 +555,7 @@ in victoriametrics = handleTest ./victoriametrics.nix {}; vikunja = handleTest ./vikunja.nix {}; virtualbox = handleTestOn ["x86_64-linux"] ./virtualbox.nix {}; + vscode-remote-ssh = handleTestOn ["x86_64-linux"] ./vscode-remote-ssh.nix {}; vscodium = discoverTests (import ./vscodium.nix); vsftpd = handleTest ./vsftpd.nix {}; wasabibackend = handleTest ./wasabibackend.nix {}; diff --git a/nixos/tests/vscode-remote-ssh.nix b/nixos/tests/vscode-remote-ssh.nix new file mode 100644 index 0000000000000..833638779d1b2 --- /dev/null +++ b/nixos/tests/vscode-remote-ssh.nix @@ -0,0 +1,141 @@ +import ./make-test-python.nix ({ lib, ... }@args: let + pkgs = args.pkgs.extend (self: super: { + stdenv = super.stdenv.override { + config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [ + "vscode" "vscode-with-extensions" "vscode-extension-ms-vscode-remote-remote-ssh" + ]; + }; + }); + + inherit (import ./ssh-keys.nix pkgs) snakeOilPrivateKey snakeOilPublicKey; + + # The commit hash for stable VS Code in Nixpkgs + rev = "c722ca6c7eed3d7987c0d5c3df5c45f6b15e77d1"; + shortRev = builtins.substring 0 8 rev; + + vscode-server = pkgs.srcOnly { + name = "vscode-server-${shortRev}"; + src = pkgs.fetchurl { + name = "vscode-server-${shortRev}.tar.gz"; + url = "https://update.code.visualstudio.com/commit:${rev}/server-linux-x64/stable"; + sha256 = "16fh0ysnxa3ag0cygv4a0p5ld3rn1ala1v03f11c56lqjgr65cfc"; + }; + }; +in { + name = "vscode-remote-ssh"; + meta.maintainers = with lib.maintainers; [ Enzime ]; + + nodes = let + serverAddress = "192.168.0.2"; + clientAddress = "192.168.0.1"; + in { + server = { ... }: { + networking.interfaces.eth1.ipv4.addresses = [ { address = serverAddress; prefixLength = 24; } ]; + services.openssh.enable = true; + users.users.root.openssh.authorizedKeys.keys = [ snakeOilPublicKey ]; + virtualisation.additionalPaths = [ pkgs.nodejs-12_x pkgs.nodejs-14_x ]; + }; + client = { ... }: { + imports = [ ./common/x11.nix ./common/user-account.nix ]; + networking.interfaces.eth1.ipv4.addresses = [ { address = clientAddress; prefixLength = 24; } ]; + networking.hosts.${serverAddress} = [ "server" ]; + test-support.displayManager.auto.user = "alice"; + environment.systemPackages = [ + (pkgs.vscode-with-extensions.override { + vscodeExtensions = [ + pkgs.vscode-extensions.ms-vscode-remote.remote-ssh + ]; + }) + ]; + }; + }; + + enableOCR = true; + + testScript = let + jq = "${pkgs.jq}/bin/jq"; + + ssh-config = builtins.toFile "ssh.conf" '' + UserKnownHostsFile=/dev/null + StrictHostKeyChecking=no + ''; + + vscode-config = builtins.toFile "settings.json" '' + { + "window.zoomLevel": 1, + "security.workspace.trust.startupPrompt": "always" + } + ''; + in '' + def connect_with_remote_ssh(screenshot, should_succeed): + print(f"connect_with_remote_ssh({screenshot=}, {should_succeed=})") + + if server.execute("test -d ~/.vscode-server")[0] == 0: + server.succeed("rm -r ~/.vscode-server") + + server.succeed("mkdir -p ~/.vscode-server/bin") + server.succeed("cp -r ${vscode-server} ~/.vscode-server/bin/${rev}") + + client.succeed("sudo -u alice code --remote=ssh-remote+root@server /root") + client.wait_for_window("Visual Studio Code") + + client.wait_for_text("Do you trust the authors" if should_succeed else "Disconnected from SSH") + client.screenshot(screenshot) + + if should_succeed: + # Press the Don't Trust button + client.send_key("tab") + client.send_key("\n") + else: + # Close the error dialog + client.send_key("esc") + + client.send_key("ctrl-q") + client.wait_until_fails("pidof code") + + + start_all() + server.wait_for_open_port(22) + + VSCODE_COMMIT = server.execute("${jq} -r .commit ${pkgs.vscode}/lib/vscode/resources/app/product.json")[1].rstrip() + SERVER_COMMIT = server.execute("${jq} -r .commit ${vscode-server}/product.json")[1].rstrip() + + print(f"{VSCODE_COMMIT=} {SERVER_COMMIT=}") + assert VSCODE_COMMIT == SERVER_COMMIT, "VSCODE_COMMIT and SERVER_COMMIT do not match" + + client.wait_until_succeeds("ping -c1 server") + client.succeed("sudo -u alice mkdir ~alice/.ssh") + client.succeed("sudo -u alice install -Dm 600 ${snakeOilPrivateKey} ~alice/.ssh/id_ecdsa") + client.succeed("sudo -u alice install ${ssh-config} ~alice/.ssh/config") + client.succeed("sudo -u alice install -Dm 644 ${vscode-config} ~alice/.config/Code/User/settings.json") + + client.wait_for_x() + client.wait_for_file("~alice/.Xauthority") + client.succeed("xauth merge ~alice/.Xauthority") + # Move the mouse out of the way + client.succeed("${pkgs.xdotool}/bin/xdotool mousemove 0 0") + + with subtest("fails to connect when Node is broken"): + server.fail("node -v") + connect_with_remote_ssh(screenshot="no_node_installed", should_succeed=False) + server.succeed("test -e ~/.vscode-server/bin/*/node") + server.fail("~/.vscode-server/bin/*/node -v") + + with subtest("fails to connect when server has the wrong Node installed"): + server.succeed("nix-env -i ${pkgs.nodejs-12_x}") + connect_with_remote_ssh(screenshot="wrong_node_installed", should_succeed=False) + server.fail("~/.vscode-server/bin/*/node -v") + + with subtest("connects when server has the correct Node installed"): + server.succeed("nix-env -i ${pkgs.nodejs-14_x}") + connect_with_remote_ssh(screenshot="correct_node_installed", should_succeed=True) + server.succeed("~/.vscode-server/bin/*/node -v") + server.succeed("kill $(pgrep -f vscode-server)") + server.succeed("nix-env -e nodejs") + + with subtest("connects when server can build Node from Nixpkgs"): + server.succeed("mkdir -p /nix/var/nix/profiles/per-user/root/channels") + server.succeed("ln -s ${pkgs.path} /nix/var/nix/profiles/per-user/root/channels/nixos") + connect_with_remote_ssh(screenshot="build_node_with_nix", should_succeed=True) + ''; +}) diff --git a/pkgs/applications/editors/vscode/extensions/remote-ssh/default.nix b/pkgs/applications/editors/vscode/extensions/remote-ssh/default.nix index 3bfc94bb6ea4c..e5715641c74db 100644 --- a/pkgs/applications/editors/vscode/extensions/remote-ssh/default.nix +++ b/pkgs/applications/editors/vscode/extensions/remote-ssh/default.nix @@ -1,4 +1,5 @@ { lib +, nixosTests , vscode-utils , useLocalExtensions ? false }: @@ -9,46 +10,84 @@ let inherit (vscode-utils) buildVscodeMarketplaceExtension; - # patch runs on remote machine hence use of which - # links to local node if version is 12 + # As VS Code executes this code on the remote machine + # we test to see if we can build Node 14 from Nixpkgs + # otherwise we use the local Node if it is version 14 patch = '' - f="$HOME/.vscode-server/bin/$COMMIT_ID/node" - localNodePath=''$(which node) - if [ -x "''$localNodePath" ]; then - localNodeVersion=''$(node -v) - if [ "\''${localNodeVersion:1:2}" = "12" ]; then - echo PATCH: replacing ''$f with ''$localNodePath - rm ''$f - ln -s ''$localNodePath ''$f + d="$HOME/.vscode-server/bin/$COMMIT_ID" + f="$d/node" + echo "VS Code Node: $f" + + # Check if VS Code Server has a non-working Node or the wrong version of Node + if ! nodeVersion=$($f -v) || [ "\''${nodeVersion:1:2}" != "14" ]; then + echo "VS Code Node Version: $nodeVersion" + + if [ -e $(nix-build "" -A nodejs-14_x --out-link "$d/nix")/bin/node ]; then + nodePath="$d/nix/bin/node" + fi + + echo "Node from Nix: $nodePath" + + nodeVersion=$($nodePath -v) + echo "Node from Nix Version: $nodeVersion" + + if [ "\''${nodeVersion:1:2}" != "14" ]; then + echo "Getting Node from Nix failed, use Local Node instead" + nodePath=$(which node) + echo "Local Node: $nodePath" + nodeVersion=$($nodePath -v) + echo "Local Node Version: $nodeVersion" + fi + + if [ "\''${nodeVersion:1:2}" == "14" ]; then + echo PATCH: replacing $f with $nodePath + rm $f + ln -s $nodePath $f fi fi + + nodeVersion=$($f -v) + echo "VS Code Node Version: $($f -v)" + + if [ "\''${nodeVersion:1:2}" != "14" ]; then + echo "Unsupported VS Code Node version: $nodeVersion", quitting + fail_with_exitcode ''${o.InstallExitCode.ServerTransferFailed} + fi + ${lib.optionalString useLocalExtensions '' # Use local extensions if [ -d $HOME/.vscode/extensions ]; then - if ! test -L "$HOME/.vscode-server/extensions"; then + if ! [ -L $HOME/.vscode-server/extensions ]; then + if [ -e $HOME/.vscode-server/extensions ]; then + mv $HOME/.vscode-server/extensions $HOME/.vscode-server/extensions.bak + fi + mkdir -p $HOME/.vscode-server - ln -s $HOME/.vscode/extensions $HOME/.vscode-server/ + ln -s $HOME/.vscode/extensions $HOME/.vscode-server/extensions fi fi ''} - ''; + + echo "Checking $VSCH_LOGFILE''; # Don't add a trailing newline as we only matched part of a command in buildVscodeMarketplaceExtension { mktplcRef = { name = "remote-ssh"; publisher = "ms-vscode-remote"; - version = "0.66.1"; - sha256 = "sha256-+v4UnGRG5xOc8k0IzvHUBHa128fhgd3jcmEuciiMQmI="; + version = "0.76.1"; + sha256 = "sha256-iLgGkf9hx75whXI+kmkmiGw3fnkEGp37Ae7GMdAz0+Y="; }; postPatch = '' substituteInPlace "out/extension.js" \ - --replace "# install extensions" '${patch}' + --replace 'echo "Checking $VSCH_LOGFILE' '${patch}' ''; + passthru.tests = { inherit (nixosTests) vscode-remote-ssh; }; + meta = with lib; { description = "Use any remote machine with a SSH server as your development environment."; license = licenses.unfree; - maintainers = with maintainers; [ SuperSandro2000 tbenst ]; + maintainers = with maintainers; [ SuperSandro2000 tbenst Enzime ]; }; } diff --git a/pkgs/applications/editors/vscode/update-vscode.sh b/pkgs/applications/editors/vscode/update-vscode.sh index 67ec7a21b3461..3a1cfd5410ed8 100755 --- a/pkgs/applications/editors/vscode/update-vscode.sh +++ b/pkgs/applications/editors/vscode/update-vscode.sh @@ -14,15 +14,37 @@ if [ ! -f "$ROOT/vscode.nix" ]; then exit 1 fi +NIXPKGS_ROOT="$(dirname $(dirname $(dirname $(dirname $ROOT))))" + +if [ ! -f "$NIXPKGS_ROOT/nixos/tests/vscode-remote-ssh.nix" ]; then + echo "ERROR: cannot find nixos/tests/vscode-remote-ssh.nix" + exit 1 +fi + # VSCode VSCODE_VER=$(curl --fail --silent https://api.github.com/repos/Microsoft/vscode/releases/latest | jq --raw-output .tag_name) sed -i "s/version = \".*\"/version = \"${VSCODE_VER}\"/" "$ROOT/vscode.nix" +TEMP_FOLDER=$(mktemp -d) + VSCODE_X64_LINUX_URL="https://update.code.visualstudio.com/${VSCODE_VER}/linux-x64/stable" -VSCODE_X64_LINUX_SHA256=$(nix-prefetch-url ${VSCODE_X64_LINUX_URL}) + +# Split output by newlines into Bash array +readarray -t VSCODE_X64_LINUX <<< $(nix-prefetch-url --print-path ${VSCODE_X64_LINUX_URL}) + +VSCODE_X64_LINUX_SHA256=${VSCODE_X64_LINUX[0]} +VSCODE_X64_LINUX_PATH=${VSCODE_X64_LINUX[1]} sed -i "s/x86_64-linux = \".\{52\}\"/x86_64-linux = \"${VSCODE_X64_LINUX_SHA256}\"/" "$ROOT/vscode.nix" +tar xf $VSCODE_X64_LINUX_PATH -C $TEMP_FOLDER +VSCODE_COMMIT=$(jq --raw-output .commit $TEMP_FOLDER/VSCode-linux-x64/resources/app/product.json) +sed -i "s/rev = \".\{40\}\"/rev = \"${VSCODE_COMMIT}\"/" "$NIXPKGS_ROOT/nixos/tests/vscode-remote-ssh.nix" + +SERVER_X64_LINUX_URL="https://update.code.visualstudio.com/commit:${VSCODE_COMMIT}/server-linux-x64/stable" +SERVER_X64_LINUX_SHA256=$(nix-prefetch-url ${SERVER_X64_LINUX_URL}) +sed -i "s/sha256 = \".\{51,52\}\"/sha256 = \"${SERVER_X64_LINUX_SHA256}\"/" "$NIXPKGS_ROOT/nixos/tests/vscode-remote-ssh.nix" + VSCODE_X64_DARWIN_URL="https://update.code.visualstudio.com/${VSCODE_VER}/darwin/stable" VSCODE_X64_DARWIN_SHA256=$(nix-prefetch-url ${VSCODE_X64_DARWIN_URL}) sed -i "s/x86_64-darwin = \".\{52\}\"/x86_64-darwin = \"${VSCODE_X64_DARWIN_SHA256}\"/" "$ROOT/vscode.nix" diff --git a/pkgs/applications/editors/vscode/vscode.nix b/pkgs/applications/editors/vscode/vscode.nix index 370647de1fcff..efb4ae21044ae 100644 --- a/pkgs/applications/editors/vscode/vscode.nix +++ b/pkgs/applications/editors/vscode/vscode.nix @@ -1,4 +1,4 @@ -{ stdenv, lib, callPackage, fetchurl, isInsiders ? false }: +{ stdenv, lib, callPackage, fetchurl, nixosTests, isInsiders ? false }: let inherit (stdenv.hostPlatform) system; @@ -24,6 +24,7 @@ in callPackage ./generic.nix rec { # Please backport all compatible updates to the stable release. # This is important for the extension ecosystem. + # Please update the commit hash in the vscode-remote-ssh test as well. version = "1.65.2"; pname = "vscode"; @@ -39,6 +40,8 @@ in sourceRoot = ""; + tests = { inherit (nixosTests) vscode-remote-ssh; }; + updateScript = ./update-vscode.sh; meta = with lib; { @@ -57,7 +60,7 @@ in homepage = "https://code.visualstudio.com/"; downloadPage = "https://code.visualstudio.com/Updates"; license = licenses.unfree; - maintainers = with maintainers; [ eadwu synthetica maxeaubrey bobby285271 ]; + maintainers = with maintainers; [ eadwu synthetica maxeaubrey bobby285271 Enzime ]; platforms = [ "x86_64-linux" "x86_64-darwin" "aarch64-darwin" "aarch64-linux" "armv7l-linux" ]; }; } diff --git a/pkgs/build-support/src-only/default.nix b/pkgs/build-support/src-only/default.nix index c721fdf40c69a..7c00a773b697b 100644 --- a/pkgs/build-support/src-only/default.nix +++ b/pkgs/build-support/src-only/default.nix @@ -1,7 +1,6 @@ { stdenv }@orig: # srcOnly is a utility builder that only fetches and unpacks the given `src`, -# maybe pathings it in the process with the optional `patches` and -# `buildInputs` attributes. +# and optionally patching with `patches` or adding build inputs. # # It can be invoked directly, or be used to wrap an existing derivation. Eg: #