Merge pull request #207646 from Enzime/vsce/test-remote-ssh
This commit is contained in:
commit
60d31a2a46
|
@ -814,6 +814,7 @@ in {
|
||||||
victoriametrics = handleTest ./victoriametrics.nix {};
|
victoriametrics = handleTest ./victoriametrics.nix {};
|
||||||
vikunja = handleTest ./vikunja.nix {};
|
vikunja = handleTest ./vikunja.nix {};
|
||||||
virtualbox = handleTestOn ["x86_64-linux"] ./virtualbox.nix {};
|
virtualbox = handleTestOn ["x86_64-linux"] ./virtualbox.nix {};
|
||||||
|
vscode-remote-ssh = handleTestOn ["x86_64-linux"] ./vscode-remote-ssh.nix {};
|
||||||
vscodium = discoverTests (import ./vscodium.nix);
|
vscodium = discoverTests (import ./vscodium.nix);
|
||||||
vsftpd = handleTest ./vsftpd.nix {};
|
vsftpd = handleTest ./vsftpd.nix {};
|
||||||
warzone2100 = handleTest ./warzone2100.nix {};
|
warzone2100 = handleTest ./warzone2100.nix {};
|
||||||
|
|
124
nixos/tests/vscode-remote-ssh.nix
Normal file
124
nixos/tests/vscode-remote-ssh.nix
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
import ./make-test-python.nix ({ lib, ... }@args: let
|
||||||
|
pkgs = args.pkgs.extend (self: super: {
|
||||||
|
stdenv = super.stdenv.override {
|
||||||
|
config = super.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;
|
||||||
|
|
||||||
|
inherit (pkgs.vscode.passthru) rev vscodeServer;
|
||||||
|
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 = with pkgs; [ patchelf bintools stdenv.cc.cc.lib ];
|
||||||
|
};
|
||||||
|
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";
|
||||||
|
|
||||||
|
sshConfig = builtins.toFile "ssh.conf" ''
|
||||||
|
UserKnownHostsFile=/dev/null
|
||||||
|
StrictHostKeyChecking=no
|
||||||
|
'';
|
||||||
|
|
||||||
|
vscodeConfig = 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 ${vscodeServer} ~/.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("tab")
|
||||||
|
client.send_key("tab")
|
||||||
|
client.send_key("\n")
|
||||||
|
else:
|
||||||
|
# Close the error dialog
|
||||||
|
client.send_key("esc")
|
||||||
|
|
||||||
|
# Don't send Ctrl-q too quickly otherwise it might not get sent to VS Code
|
||||||
|
client.sleep(1)
|
||||||
|
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 ${vscodeServer}/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 ${sshConfig} ~alice/.ssh/config")
|
||||||
|
client.succeed("sudo -u alice install -Dm 644 ${vscodeConfig} ~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 nixpkgs isn't available"):
|
||||||
|
server.fail("nix-build '<nixpkgs>' -A hello")
|
||||||
|
connect_with_remote_ssh(screenshot="no_node_installed", should_succeed=False)
|
||||||
|
server.succeed("test -e ~/.vscode-server/bin/${rev}/node")
|
||||||
|
server.fail("~/.vscode-server/bin/${rev}/node -v")
|
||||||
|
|
||||||
|
with subtest("connects when server can patch Node"):
|
||||||
|
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)
|
||||||
|
'';
|
||||||
|
})
|
|
@ -1,4 +1,5 @@
|
||||||
{ lib
|
{ lib
|
||||||
|
, nixosTests
|
||||||
, vscode-utils
|
, vscode-utils
|
||||||
, useLocalExtensions ? false
|
, useLocalExtensions ? false
|
||||||
}:
|
}:
|
||||||
|
@ -9,8 +10,6 @@
|
||||||
let
|
let
|
||||||
inherit (vscode-utils) buildVscodeMarketplaceExtension;
|
inherit (vscode-utils) buildVscodeMarketplaceExtension;
|
||||||
|
|
||||||
nodeVersion = "16";
|
|
||||||
|
|
||||||
# As VS Code executes this code on the remote machine
|
# As VS Code executes this code on the remote machine
|
||||||
# we test to see if we can build Node from Nixpkgs
|
# we test to see if we can build Node from Nixpkgs
|
||||||
# otherwise we check if the globally installed Node
|
# otherwise we check if the globally installed Node
|
||||||
|
@ -23,38 +22,44 @@ let
|
||||||
serverNode="$serverDir/node"
|
serverNode="$serverDir/node"
|
||||||
echo "VS Code Node: $serverNode"
|
echo "VS Code Node: $serverNode"
|
||||||
|
|
||||||
# Check if VS Code Server has a non-working Node or the wrong version of Node
|
# Check if Node included with VS Code Server runs
|
||||||
if ! nodeVersion=$($serverNode -v) || [ "\''${nodeVersion:1:2}" != "${nodeVersion}" ]; then
|
if ! nodeVersion=$($serverNode -v); then
|
||||||
echo "VS Code Node Version: $nodeVersion"
|
echo "VS Code Node Version: $nodeVersion"
|
||||||
|
|
||||||
if nix-build "<nixpkgs>" -A nodejs-${nodeVersion}_x --out-link "$serverDir/nix" && [ -e "$serverDir/nix/bin/node" ]; then
|
if ! nix-build "<nixpkgs>" -A patchelf --out-link "$serverDir/patchelf" || ! "$serverDir/patchelf/bin/patchelf" --version; then
|
||||||
nodePath="$serverDir/nix/bin/node"
|
echo "Failed to get patchelf from nixpkgs"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Node from Nix: $nodePath"
|
if [ -e $serverNode.orig ]; then
|
||||||
|
cp $serverNode.orig $serverNode
|
||||||
nodeVersion=$($nodePath -v)
|
else
|
||||||
echo "Node from Nix Version: $nodeVersion"
|
cp $serverNode $serverNode.orig
|
||||||
|
|
||||||
if [ "\''${nodeVersion:1:2}" != "${nodeVersion}" ]; 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
|
fi
|
||||||
|
|
||||||
if [ "\''${nodeVersion:1:2}" == "${nodeVersion}" ]; then
|
if ! nix-build "<nixpkgs>" -A bintools --out-link $serverDir/bintools; then
|
||||||
echo PATCH: replacing $serverNode with $nodePath
|
echo "Failed to build bintools from nixpkgs"
|
||||||
ln -sf $nodePath $serverNode
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
INTERPRETER=$(cat $serverDir/bintools/nix-support/dynamic-linker)
|
||||||
|
|
||||||
|
echo "Interpreter from bintools: $INTERPRETER"
|
||||||
|
|
||||||
|
if ! nix-build "<nixpkgs>" -A stdenv.cc.cc.lib --out-link $serverDir/cc; then
|
||||||
|
echo "Failed to build stdenv.cc.cc.lib from nixpkgs"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! $serverDir/patchelf/bin/patchelf --set-interpreter $INTERPRETER --set-rpath $serverDir/cc-lib/lib $serverNode; then
|
||||||
|
echo "Failed to patch Node binary"
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm "$serverDir/patchelf"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
nodeVersion=$($serverNode -v)
|
nodeVersion=$($serverNode -v)
|
||||||
echo "VS Code Node Version: $nodeVersion"
|
echo "VS Code Node Version: $nodeVersion"
|
||||||
|
|
||||||
if [ "\''${nodeVersion:1:2}" != "${nodeVersion}" ]; then
|
if ! nodeVersion=$($serverNode -v); then
|
||||||
echo "Unsupported VS Code Node version: $nodeVersion", quitting
|
echo "Unable to fix Node binary, quitting"
|
||||||
fail_with_exitcode ''${o.InstallExitCode.ServerTransferFailed}
|
fail_with_exitcode ''${o.InstallExitCode.ServerTransferFailed}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -87,6 +92,8 @@ buildVscodeMarketplaceExtension {
|
||||||
--replace '# Start the server\n' '${patch}'
|
--replace '# Start the server\n' '${patch}'
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
passthru.tests = { inherit (nixosTests) vscode-remote-ssh; };
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
description = "Use any remote machine with a SSH server as your development environment.";
|
description = "Use any remote machine with a SSH server as your development environment.";
|
||||||
license = lib.licenses.unfree;
|
license = lib.licenses.unfree;
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
, version, src, meta, sourceRoot, commandLineArgs
|
, version, src, meta, sourceRoot, commandLineArgs
|
||||||
, executableName, longName, shortName, pname, updateScript
|
, executableName, longName, shortName, pname, updateScript
|
||||||
, dontFixup ? false
|
, dontFixup ? false
|
||||||
|
, rev ? null, vscodeServer ? null
|
||||||
|
|
||||||
# sourceExecutableName is the name of the binary in the source archive, over
|
# sourceExecutableName is the name of the binary in the source archive, over
|
||||||
# which we have no control
|
# which we have no control
|
||||||
, sourceExecutableName ? executableName
|
, sourceExecutableName ? executableName
|
||||||
|
@ -30,6 +32,8 @@ let
|
||||||
inherit executableName longName tests updateScript;
|
inherit executableName longName tests updateScript;
|
||||||
fhs = fhs {};
|
fhs = fhs {};
|
||||||
fhsWithPackages = f: fhs { additionalPkgs = f; };
|
fhsWithPackages = f: fhs { additionalPkgs = f; };
|
||||||
|
} // lib.optionalAttrs (vscodeServer != null) {
|
||||||
|
inherit rev vscodeServer;
|
||||||
};
|
};
|
||||||
|
|
||||||
desktopItem = makeDesktopItem {
|
desktopItem = makeDesktopItem {
|
||||||
|
|
|
@ -19,9 +19,22 @@ fi
|
||||||
VSCODE_VER=$(curl --fail --silent https://api.github.com/repos/Microsoft/vscode/releases/latest | jq --raw-output .tag_name)
|
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"
|
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_URL="https://update.code.visualstudio.com/${VSCODE_VER}/linux-x64/stable"
|
||||||
VSCODE_X64_LINUX_SHA256=$(nix-prefetch-url ${VSCODE_X64_LINUX_URL})
|
|
||||||
sed -i "s/x86_64-linux = \".\{52\}\"/x86_64-linux = \"${VSCODE_X64_LINUX_SHA256}\"/" "$ROOT/vscode.nix"
|
# Split output by newlines into Bash array
|
||||||
|
readarray -t VSCODE_X64_LINUX <<< $(nix-prefetch-url --print-path ${VSCODE_X64_LINUX_URL})
|
||||||
|
|
||||||
|
sed -i "s/x86_64-linux = \".\{52\}\"/x86_64-linux = \"${VSCODE_X64_LINUX[0]}\"/" "$ROOT/vscode.nix"
|
||||||
|
|
||||||
|
tar xf ${VSCODE_X64_LINUX[1]} -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}\"/" "$ROOT/vscode.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}\"/" "$ROOT/vscode.nix"
|
||||||
|
|
||||||
VSCODE_X64_DARWIN_URL="https://update.code.visualstudio.com/${VSCODE_VER}/darwin/stable"
|
VSCODE_X64_DARWIN_URL="https://update.code.visualstudio.com/${VSCODE_VER}/darwin/stable"
|
||||||
VSCODE_X64_DARWIN_SHA256=$(nix-prefetch-url ${VSCODE_X64_DARWIN_URL})
|
VSCODE_X64_DARWIN_SHA256=$(nix-prefetch-url ${VSCODE_X64_DARWIN_URL})
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
{ stdenv, lib, callPackage, fetchurl
|
{ stdenv
|
||||||
|
, lib
|
||||||
|
, callPackage
|
||||||
|
, fetchurl
|
||||||
|
, nixosTests
|
||||||
|
, srcOnly
|
||||||
, isInsiders ? false
|
, isInsiders ? false
|
||||||
, commandLineArgs ? ""
|
, commandLineArgs ? ""
|
||||||
, useVSCodeRipgrep ? stdenv.isDarwin
|
, useVSCodeRipgrep ? stdenv.isDarwin
|
||||||
|
@ -32,6 +37,9 @@ in
|
||||||
version = "1.79.1";
|
version = "1.79.1";
|
||||||
pname = "vscode";
|
pname = "vscode";
|
||||||
|
|
||||||
|
# This is used for VS Code - Remote SSH test
|
||||||
|
rev = "b380da4ef1ee00e224a15c1d4d9793e27c2b6302";
|
||||||
|
|
||||||
executableName = "code" + lib.optionalString isInsiders "-insiders";
|
executableName = "code" + lib.optionalString isInsiders "-insiders";
|
||||||
longName = "Visual Studio Code" + lib.optionalString isInsiders " - Insiders";
|
longName = "Visual Studio Code" + lib.optionalString isInsiders " - Insiders";
|
||||||
shortName = "Code" + lib.optionalString isInsiders " - Insiders";
|
shortName = "Code" + lib.optionalString isInsiders " - Insiders";
|
||||||
|
@ -48,6 +56,18 @@ in
|
||||||
|
|
||||||
sourceRoot = "";
|
sourceRoot = "";
|
||||||
|
|
||||||
|
# As tests run without networking, we need to download this for the Remote SSH server
|
||||||
|
vscodeServer = srcOnly {
|
||||||
|
name = "vscode-server-${rev}.tar.gz";
|
||||||
|
src = fetchurl {
|
||||||
|
name = "vscode-server-${rev}.tar.gz";
|
||||||
|
url = "https://update.code.visualstudio.com/commit:${rev}/server-linux-x64/stable";
|
||||||
|
sha256 = "0732wpl4fjknhn423k23zrcqz9psjj1iy8lqa0fc8970n1m7i58b";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
tests = { inherit (nixosTests) vscode-remote-ssh; };
|
||||||
|
|
||||||
updateScript = ./update-vscode.sh;
|
updateScript = ./update-vscode.sh;
|
||||||
|
|
||||||
# Editing the `code` binary within the app bundle causes the bundle's signature
|
# Editing the `code` binary within the app bundle causes the bundle's signature
|
||||||
|
@ -71,7 +91,7 @@ in
|
||||||
homepage = "https://code.visualstudio.com/";
|
homepage = "https://code.visualstudio.com/";
|
||||||
downloadPage = "https://code.visualstudio.com/Updates";
|
downloadPage = "https://code.visualstudio.com/Updates";
|
||||||
license = licenses.unfree;
|
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" ];
|
platforms = [ "x86_64-linux" "x86_64-darwin" "aarch64-darwin" "aarch64-linux" "armv7l-linux" ];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
{ stdenv }:
|
{ stdenv }:
|
||||||
# srcOnly is a utility builder that only fetches and unpacks the given `src`,
|
# srcOnly is a utility builder that only fetches and unpacks the given `src`,
|
||||||
# maybe pathings it in the process with the optional `patches` and
|
# and optionally patching with `patches` or adding build inputs.
|
||||||
# `buildInputs` attributes.
|
|
||||||
#
|
#
|
||||||
# It can be invoked directly, or be used to wrap an existing derivation. Eg:
|
# It can be invoked directly, or be used to wrap an existing derivation. Eg:
|
||||||
#
|
#
|
||||||
|
|
Loading…
Reference in a new issue