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.0";
62
63 src = fetchFromGitHub {
64 owner = "gitpod-io";
65 repo = "openvscode-server";
66 rev = "openvscode-server-v${finalAttrs.version}";
67 hash = "sha256-dVzGyK1ybZywCm602zWJroSCQ2wx5IzV+HqwZUsEgKU=";
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 buildInputs = lib.optionals (!stdenv.isDarwin) [ libsecret ]
104 ++ (with xorg; [ libX11 libxkbfile ])
105 ++ lib.optionals stdenv.isDarwin [
106 AppKit
107 Cocoa
108 Security
109 cctools
110 ];
111
112 patches = [
113 # Patch out remote download of nodejs from build script
114 ./remove-node-download.patch
115 ];
116
117 postPatch = ''
118 export HOME=$PWD
119
120 # remove all built-in extensions, as these are 3rd party extensions that
121 # get downloaded from vscode marketplace
122 jq --slurp '.[0] * .[1]' "product.json" <(
123 cat << EOF
124 {
125 "builtInExtensions": []
126 }
127 EOF
128 ) | sponge product.json
129 '';
130
131 configurePhase = ''
132 runHook preConfigure
133
134 # set default yarn opts
135 ${lib.concatMapStrings (option: ''
136 yarn --offline config set ${option}
137 '') defaultYarnOpts}
138
139 # set offline mirror to yarn cache we created in previous steps
140 yarn --offline config set yarn-offline-mirror "${finalAttrs.yarnCache}"
141
142 # set nodedir, so we can build binaries later
143 npm config set nodedir "${nodejs}"
144
145 runHook postConfigure
146 '';
147
148 buildPhase = ''
149 runHook preBuild
150
151 # install dependencies
152 yarn --offline --ignore-scripts
153
154 # run yarn install everywhere, skipping postinstall so we can patch esbuild
155 find . -path "*node_modules" -prune -o \
156 -path "./*/*" -name "yarn.lock" -printf "%h\n" | \
157 xargs -I {} yarn --cwd {} \
158 --frozen-lockfile --offline --ignore-scripts --ignore-engines
159
160 ${patchEsbuild "./build" "0.12.6"}
161 ${patchEsbuild "./extensions" "0.11.23"}
162
163 # patch shebangs of node_modules to allow binary packages to build
164 patchShebangs ./remote/node_modules
165
166 # put ripgrep binary into bin so postinstall does not try to download it
167 find -path "*@vscode/ripgrep" -type d \
168 -execdir mkdir -p {}/bin \; \
169 -execdir ln -s ${ripgrep}/bin/rg {}/bin/rg \;
170 '' + lib.optionalString stdenv.isDarwin ''
171 # use prebuilt binary for @parcel/watcher, which requires macOS SDK 10.13+
172 # (see issue #101229)
173 pushd ./remote/node_modules/@parcel/watcher
174 mkdir -p ./build/Release
175 mv ./prebuilds/darwin-x64/node.napi.glibc.node ./build/Release/watcher.node
176 jq "del(.scripts) | .gypfile = false" ./package.json | sponge ./package.json
177 popd
178 '' + ''
179 export NODE_OPTIONS=--openssl-legacy-provider
180
181 # rebuild binaries, we use npm here, as yarn does not provide an alternative
182 # that would not attempt to try to reinstall everything and break our
183 # patching attempts
184 npm --prefix ./remote rebuild --build-from-source
185
186 # run postinstall scripts after patching
187 find . -path "*node_modules" -prune -o \
188 -path "./*/*" -name "yarn.lock" -printf "%h\n" | \
189 xargs -I {} sh -c 'jq -e ".scripts.postinstall" {}/package.json >/dev/null && yarn --cwd {} postinstall --frozen-lockfile --offline || true'
190
191 # build and minify
192 yarn --offline gulp vscode-reh-web-${vsBuildTarget}-min
193
194 runHook postBuild
195 '';
196
197 installPhase = ''
198 runHook preInstall
199
200 mkdir -p $out
201 cp -R -T ../vscode-reh-web-${vsBuildTarget} $out
202 ln -s ${nodejs}/bin/node $out
203
204 runHook postInstall
205 '';
206
207 passthru.tests = {
208 inherit (nixosTests) openvscode-server;
209 };
210
211 meta = {
212 description = "Run VS Code on a remote machine";
213 longDescription = ''
214 Run upstream VS Code on a remote machine with access through a modern web
215 browser from any device, anywhere.
216 '';
217 homepage = "https://github.com/gitpod-io/openvscode-server";
218 license = lib.licenses.mit;
219 maintainers = with lib.maintainers; [ dguenther ghuntley emilytrau ];
220 platforms = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
221 };
222})