1{ lib
2, stdenv
3, fetchFromGitHub
4, buildGoModule
5, makeWrapper
6, cacert
7, moreutils
8, jq
9, git
10, pkg-config
11, yarn
12, python3
13, esbuild
14, nodejs
15, libsecret
16, xorg
17, ripgrep
18, AppKit
19, Cocoa
20, Security
21, cctools
22, nixosTests
23}:
24
25let
26 system = stdenv.hostPlatform.system;
27
28 yarn' = yarn.override { inherit nodejs; };
29 defaultYarnOpts = [ "frozen-lockfile" "non-interactive" "no-progress" ];
30
31 vsBuildTarget = {
32 x86_64-linux = "linux-x64";
33 aarch64-linux = "linux-arm64";
34 x86_64-darwin = "darwin-x64";
35 aarch64-darwin = "darwin-arm64";
36 }.${system} or (throw "Unsupported system ${system}");
37
38 esbuild' = esbuild.override {
39 buildGoModule = args: buildGoModule (args // rec {
40 version = "0.16.17";
41 src = fetchFromGitHub {
42 owner = "evanw";
43 repo = "esbuild";
44 rev = "v${version}";
45 hash = "sha256-8L8h0FaexNsb3Mj6/ohA37nYLFogo5wXkAhGztGUUsQ=";
46 };
47 vendorHash = "sha256-+BfxCyg0KkDQpHt/wycy/8CTG6YBA/VJvJFhhzUnSiQ=";
48 });
49 };
50
51 # replaces esbuild's download script with a binary from nixpkgs
52 patchEsbuild = path: version: ''
53 mkdir -p ${path}/node_modules/esbuild/bin
54 jq "del(.scripts.postinstall)" ${path}/node_modules/esbuild/package.json | sponge ${path}/node_modules/esbuild/package.json
55 sed -i 's/${version}/${esbuild'.version}/g' ${path}/node_modules/esbuild/lib/main.js
56 ln -s -f ${esbuild'}/bin/esbuild ${path}/node_modules/esbuild/bin/esbuild
57 '';
58in
59stdenv.mkDerivation (finalAttrs: {
60 pname = "openvscode-server";
61 version = "1.79.2";
62
63 src = fetchFromGitHub {
64 owner = "gitpod-io";
65 repo = "openvscode-server";
66 rev = "openvscode-server-v${finalAttrs.version}";
67 hash = "sha256-u5LuDcKTN4CEpRnFCeEbni6hiDDwTV9LUEmXaQYJvJw=";
68 };
69
70 yarnCache = stdenv.mkDerivation {
71 name = "${finalAttrs.pname}-${finalAttrs.version}-${system}-yarn-cache";
72 inherit (finalAttrs) src;
73 nativeBuildInputs = [ cacert yarn' git ];
74 buildPhase = ''
75 export HOME=$PWD
76
77 yarn config set yarn-offline-mirror $out
78 find "$PWD" -name "yarn.lock" -printf "%h\n" | \
79 xargs -I {} yarn --cwd {} \
80 --frozen-lockfile --ignore-scripts --ignore-platform \
81 --ignore-engines --no-progress --non-interactive
82 '';
83
84 installPhase = ''
85 echo yarnCache
86 '';
87
88 outputHashMode = "recursive";
89 outputHashAlgo = "sha256";
90 outputHash = "sha256-P6mzeE3HnS/KoP7kCXJlDkFWkTKiGjJkOUXfGOru/xE=";
91 };
92
93 nativeBuildInputs = [
94 nodejs
95 yarn'
96 python3
97 pkg-config
98 makeWrapper
99 git
100 jq
101 moreutils
102 ];
103
104 buildInputs = lib.optionals (!stdenv.isDarwin) [ libsecret ]
105 ++ (with xorg; [ libX11 libxkbfile ])
106 ++ lib.optionals stdenv.isDarwin [
107 AppKit
108 Cocoa
109 Security
110 cctools
111 ];
112
113 patches = [
114 # Patch out remote download of nodejs from build script
115 ./remove-node-download.patch
116 ];
117
118 postPatch = ''
119 export HOME=$PWD
120
121 # remove all built-in extensions, as these are 3rd party extensions that
122 # get downloaded from vscode marketplace
123 jq --slurp '.[0] * .[1]' "product.json" <(
124 cat << EOF
125 {
126 "builtInExtensions": []
127 }
128 EOF
129 ) | sponge product.json
130 '';
131
132 configurePhase = ''
133 runHook preConfigure
134
135 # set default yarn opts
136 ${lib.concatMapStrings (option: ''
137 yarn --offline config set ${option}
138 '') defaultYarnOpts}
139
140 # set offline mirror to yarn cache we created in previous steps
141 yarn --offline config set yarn-offline-mirror "${finalAttrs.yarnCache}"
142
143 # set nodedir, so we can build binaries later
144 npm config set nodedir "${nodejs}"
145
146 runHook postConfigure
147 '';
148
149 buildPhase = ''
150 runHook preBuild
151
152 # install dependencies
153 yarn --offline --ignore-scripts
154
155 # run yarn install everywhere, skipping postinstall so we can patch esbuild
156 find . -path "*node_modules" -prune -o \
157 -path "./*/*" -name "yarn.lock" -printf "%h\n" | \
158 xargs -I {} yarn --cwd {} \
159 --frozen-lockfile --offline --ignore-scripts --ignore-engines
160
161 ${patchEsbuild "./build" "0.12.6"}
162 ${patchEsbuild "./extensions" "0.11.23"}
163
164 # patch shebangs of node_modules to allow binary packages to build
165 patchShebangs ./remote/node_modules
166
167 # put ripgrep binary into bin so postinstall does not try to download it
168 find -path "*@vscode/ripgrep" -type d \
169 -execdir mkdir -p {}/bin \; \
170 -execdir ln -s ${ripgrep}/bin/rg {}/bin/rg \;
171 '' + lib.optionalString stdenv.isDarwin ''
172 # use prebuilt binary for @parcel/watcher, which requires macOS SDK 10.13+
173 # (see issue #101229)
174 pushd ./remote/node_modules/@parcel/watcher
175 mkdir -p ./build/Release
176 mv ./prebuilds/darwin-x64/node.napi.glibc.node ./build/Release/watcher.node
177 jq "del(.scripts) | .gypfile = false" ./package.json | sponge ./package.json
178 popd
179 '' + ''
180 export NODE_OPTIONS=--openssl-legacy-provider
181
182 # rebuild binaries, we use npm here, as yarn does not provide an alternative
183 # that would not attempt to try to reinstall everything and break our
184 # patching attempts
185 npm --prefix ./remote rebuild --build-from-source
186
187 # run postinstall scripts after patching
188 find . -path "*node_modules" -prune -o \
189 -path "./*/*" -name "yarn.lock" -printf "%h\n" | \
190 xargs -I {} sh -c 'jq -e ".scripts.postinstall" {}/package.json >/dev/null && yarn --cwd {} postinstall --frozen-lockfile --offline || true'
191
192 # build and minify
193 yarn --offline gulp vscode-reh-web-${vsBuildTarget}-min
194
195 runHook postBuild
196 '';
197
198 installPhase = ''
199 runHook preInstall
200
201 mkdir -p $out
202 cp -R -T ../vscode-reh-web-${vsBuildTarget} $out
203 ln -s ${nodejs}/bin/node $out
204
205 runHook postInstall
206 '';
207
208 passthru.tests = {
209 inherit (nixosTests) openvscode-server;
210 };
211
212 meta = {
213 description = "Run VS Code on a remote machine";
214 longDescription = ''
215 Run upstream VS Code on a remote machine with access through a modern web
216 browser from any device, anywhere.
217 '';
218 homepage = "https://github.com/gitpod-io/openvscode-server";
219 license = lib.licenses.mit;
220 maintainers = with lib.maintainers; [ dguenther ghuntley emilytrau ];
221 platforms = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
222 mainProgram = "openvscode-server";
223 };
224})