1{ lib
2, stdenv
3, fetchFromGitHub
4, buildGoModule
5, makeWrapper
6, cacert
7, moreutils
8, jq
9, git
10, rsync
11, pkg-config
12, yarn
13, python3
14, esbuild
15, nodejs
16, node-gyp
17, libsecret
18, xorg
19, ripgrep
20, AppKit
21, Cocoa
22, CoreServices
23, Security
24, cctools
25, xcbuild
26, quilt
27, nixosTests
28}:
29
30let
31 system = stdenv.hostPlatform.system;
32
33 python = python3;
34 yarn' = yarn.override { inherit nodejs; };
35 defaultYarnOpts = [ ];
36
37 esbuild' = esbuild.override {
38 buildGoModule = args: buildGoModule (args // rec {
39 version = "0.16.17";
40 src = fetchFromGitHub {
41 owner = "evanw";
42 repo = "esbuild";
43 rev = "v${version}";
44 hash = "sha256-8L8h0FaexNsb3Mj6/ohA37nYLFogo5wXkAhGztGUUsQ=";
45 };
46 vendorHash = "sha256-+BfxCyg0KkDQpHt/wycy/8CTG6YBA/VJvJFhhzUnSiQ=";
47 });
48 };
49
50 # replaces esbuild's download script with a binary from nixpkgs
51 patchEsbuild = path: version: ''
52 mkdir -p ${path}/node_modules/esbuild/bin
53 jq "del(.scripts.postinstall)" ${path}/node_modules/esbuild/package.json | sponge ${path}/node_modules/esbuild/package.json
54 sed -i 's/${version}/${esbuild'.version}/g' ${path}/node_modules/esbuild/lib/main.js
55 ln -s -f ${esbuild'}/bin/esbuild ${path}/node_modules/esbuild/bin/esbuild
56 '';
57in
58stdenv.mkDerivation (finalAttrs: {
59 pname = "code-server";
60 version = "4.12.0";
61
62 src = fetchFromGitHub {
63 owner = "coder";
64 repo = "code-server";
65 rev = "v${finalAttrs.version}";
66 fetchSubmodules = true;
67 hash = "sha256-PQp5dji2Ynp+LJRWBka41umwe1/IR76C+at/wyOWGcI=";
68 };
69
70 yarnCache = stdenv.mkDerivation {
71 name = "${finalAttrs.pname}-${finalAttrs.version}-${system}-yarn-cache";
72 inherit (finalAttrs) src;
73
74 nativeBuildInputs = [ yarn' git cacert ];
75
76 buildPhase = ''
77 export HOME=$PWD
78 export GIT_SSL_CAINFO="${cacert}/etc/ssl/certs/ca-bundle.crt"
79
80 yarn --cwd "./vendor" install --modules-folder modules --ignore-scripts --frozen-lockfile
81
82 yarn config set yarn-offline-mirror $out
83 find "$PWD" -name "yarn.lock" -printf "%h\n" | \
84 xargs -I {} yarn --cwd {} \
85 --frozen-lockfile --ignore-scripts --ignore-platform \
86 --ignore-engines --no-progress --non-interactive
87
88 find ./lib/vscode -name "yarn.lock" -printf "%h\n" | \
89 xargs -I {} yarn --cwd {} \
90 --ignore-scripts --ignore-engines
91 '';
92
93 outputHashMode = "recursive";
94 outputHashAlgo = "sha256";
95 outputHash = "sha256-4Vr9u3+W/IhbbTc39jyDyDNQODlmdF+M/N8oJn0Z4+w=";
96 };
97
98 nativeBuildInputs = [
99 nodejs
100 yarn'
101 python
102 pkg-config
103 makeWrapper
104 git
105 rsync
106 jq
107 moreutils
108 quilt
109 ];
110
111 buildInputs = lib.optionals (!stdenv.isDarwin) [ libsecret ]
112 ++ (with xorg; [ libX11 libxkbfile ])
113 ++ lib.optionals stdenv.isDarwin [
114 AppKit
115 Cocoa
116 CoreServices
117 Security
118 cctools
119 xcbuild
120 ];
121
122 patches = [
123 # remove git calls from vscode build script
124 ./build-vscode-nogit.patch
125 ];
126
127 postPatch = ''
128 export HOME=$PWD
129
130 patchShebangs ./ci
131
132 # inject git commit
133 substituteInPlace ci/build/build-release.sh \
134 --replace '$(git rev-parse HEAD)' "$commit"
135 '';
136
137 configurePhase = ''
138 runHook preConfigure
139
140 # run yarn offline by default
141 echo '--install.offline true' >> .yarnrc
142
143 # set default yarn opts
144 ${lib.concatMapStrings (option: ''
145 yarn --offline config set ${option}
146 '') defaultYarnOpts}
147
148 # set offline mirror to yarn cache we created in previous steps
149 yarn --offline config set yarn-offline-mirror "${finalAttrs.yarnCache}"
150
151 # skip unnecessary electron download
152 export ELECTRON_SKIP_BINARY_DOWNLOAD=1
153
154 # set nodedir to prevent node-gyp from downloading headers
155 # taken from https://nixos.org/manual/nixpkgs/stable/#javascript-tool-specific
156 mkdir -p $HOME/.node-gyp/${nodejs.version}
157 echo 9 > $HOME/.node-gyp/${nodejs.version}/installVersion
158 ln -sfv ${nodejs}/include $HOME/.node-gyp/${nodejs.version}
159 export npm_config_nodedir=${nodejs}
160
161 # use updated node-gyp. fixes the following error on Darwin:
162 # PermissionError: [Errno 1] Operation not permitted: '/usr/sbin/pkgutil'
163 export npm_config_node_gyp=${node-gyp}/lib/node_modules/node-gyp/bin/node-gyp.js
164
165 runHook postConfigure
166 '';
167
168 buildPhase = ''
169 runHook preBuild
170
171 # install code-server dependencies
172 yarn --offline --ignore-scripts
173
174 # apply patches
175 quilt push -a
176
177 # patch shebangs of everything to allow binary packages to build
178 patchShebangs .
179
180 export PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1
181 export SKIP_SUBMODULE_DEPS=1
182 export NODE_OPTIONS=--openssl-legacy-provider
183
184 # rebuild binary packages now that scripts have been patched
185 echo "----- NPM rebuild"
186 npm rebuild --prefer-offline
187
188 # Replicate ci/dev/postinstall.sh
189 echo "----- Replicate ci/dev/postinstall.sh"
190 yarn --cwd "./vendor" install --modules-folder modules --offline --ignore-scripts --frozen-lockfile
191
192 # remove all built-in extensions, as these are 3rd party extensions that
193 # get downloaded from vscode marketplace
194 jq --slurp '.[0] * .[1]' "./lib/vscode/product.json" <(
195 cat << EOF
196 {
197 "builtInExtensions": []
198 }
199 EOF
200 ) | sponge ./lib/vscode/product.json
201
202 # disable automatic updates
203 sed -i '/update.mode/,/\}/{s/default:.*/default: "none",/g}' \
204 lib/vscode/src/vs/platform/update/common/update.config.contribution.ts
205
206 # Patch out remote download of nodejs from build script
207 patch -p1 -i ${./remove-node-download.patch}
208
209 # Fetch packages for vscode
210 find ./lib/vscode -name "yarn.lock" -printf "%h\n" | \
211 xargs -I {} yarn --cwd {} \
212 --frozen-lockfile --ignore-scripts --ignore-engines
213
214 # patch shebangs of everything to allow binary packages to build
215 patchShebangs .
216
217 ${patchEsbuild "./lib/vscode/build" "0.12.6"}
218 ${patchEsbuild "./lib/vscode/extensions" "0.11.23"}
219 '' + lib.optionalString stdenv.isDarwin ''
220 # use prebuilt binary for @parcel/watcher, which requires macOS SDK 10.13+
221 # (see issue #101229)
222 pushd ./lib/vscode/remote/node_modules/@parcel/watcher
223 mkdir -p ./build/Release
224 mv ./prebuilds/darwin-x64/node.napi.glibc.node ./build/Release/watcher.node
225 jq "del(.scripts) | .gypfile = false" ./package.json | sponge ./package.json
226 popd
227 '' + ''
228
229 # put ripgrep binary into bin, so postinstall does not try to download it
230 find -name ripgrep -type d \
231 -execdir mkdir -p {}/bin \; \
232 -execdir ln -s ${ripgrep}/bin/rg {}/bin/rg \;
233
234 # run postinstall scripts after patching
235 find ./lib/vscode -path "*node_modules" -prune -o \
236 -path "./*/*/*/*/*" -name "yarn.lock" -printf "%h\n" | \
237 xargs -I {} sh -c 'jq -e ".scripts.postinstall" {}/package.json >/dev/null && yarn --cwd {} postinstall --frozen-lockfile --offline || true'
238
239 # build code-server
240 yarn build
241
242 # build vscode
243 VERSION=${finalAttrs.version} yarn build:vscode
244
245 # create release
246 yarn release
247
248 runHook postBuild
249 '';
250
251 installPhase = ''
252 runHook preInstall
253
254 mkdir -p $out/libexec/code-server $out/bin
255
256 # copy release to libexec path
257 cp -R -T release "$out/libexec/code-server"
258
259 # install only production dependencies
260 yarn --offline --cwd "$out/libexec/code-server" --production
261
262 # create wrapper
263 makeWrapper "${nodejs}/bin/node" "$out/bin/code-server" \
264 --add-flags "$out/libexec/code-server/out/node/entry.js"
265
266 runHook postInstall
267 '';
268
269 passthru = {
270 prefetchYarnCache = lib.overrideDerivation finalAttrs.yarnCache (d: {
271 outputHash = lib.fakeSha256;
272 });
273 tests = {
274 inherit (nixosTests) code-server;
275 };
276 };
277
278 meta = {
279 description = "Run VS Code on a remote server";
280 longDescription = ''
281 code-server is VS Code running on a remote server, accessible through the
282 browser.
283 '';
284 homepage = "https://github.com/coder/code-server";
285 license = lib.licenses.mit;
286 maintainers = with lib.maintainers; [ offline henkery ];
287 platforms = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" ];
288 };
289})