tasks.bash 10.9 KB
Newer Older
A
Asher 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
#!/bin/bash
set -euo pipefail

function log() {
	local message="${1}" ; shift
	local level="${1:-info}"
	if [[ "${level}" == "error" ]] ; then
		>&2 echo "${message}"
	else
		echo "${message}"
	fi
}

function exit-if-ci() {
	if [[ -n "${ci}" ]] ; then
		log "Pre-built VS Code ${vscodeVersion}-${target}-${arch} is incorrectly built" "error"
		exit 1
	fi
}

# Copy code-server into VS Code along with its dependencies.
function copy-server() {
A
Asher 已提交
23 24 25 26 27 28
	log "Applying patch"
	cd "${vscodeSourcePath}"
	git reset --hard
	git clean -fd
	git apply "${rootPath}/scripts/vscode.patch"

A
Asher 已提交
29 30 31 32
	local serverPath="${vscodeSourcePath}/src/vs/server"
	rm -rf "${serverPath}"
	mkdir -p "${serverPath}"

A
Asher 已提交
33
	log "Copying code-server code"
A
Asher 已提交
34

A
Asher 已提交
35 36 37
	cp -r "${rootPath}/src" "${serverPath}"
	cp -r "${rootPath}/typings" "${serverPath}"
	cp "${rootPath}/main.js" "${serverPath}"
A
Asher 已提交
38 39 40 41
	cp "${rootPath}/package.json" "${serverPath}"
	cp "${rootPath}/yarn.lock" "${serverPath}"

	if [[ -d "${rootPath}/node_modules" ]] ; then
A
Asher 已提交
42
		log "Copying code-server build dependencies"
A
Asher 已提交
43 44
		cp -r "${rootPath}/node_modules" "${serverPath}"
	else
A
Asher 已提交
45
		log "Installing code-server build dependencies"
A
Asher 已提交
46
		cd "${serverPath}"
A
Asher 已提交
47 48 49
		# Ignore scripts to avoid also installing VS Code dependencies which has
		# already been done.
		yarn --ignore-scripts
A
Asher 已提交
50 51
		rm -r node_modules/@types/node # I keep getting type conflicts
	fi
A
Asher 已提交
52 53 54 55 56

	# TODO: Duplicate identifier issue. There must be a better way to fix this.
	if [[ "${target}" == "darwin" ]] ; then
		rm "${serverPath}/node_modules/fsevents/node_modules/safe-buffer/index.d.ts"
	fi
A
Asher 已提交
57 58
}

A
Asher 已提交
59
# Prepend the nbin shim which enables finding files within the binary.
A
Asher 已提交
60 61
function prepend-loader() {
	local filePath="${codeServerBuildPath}/${1}" ; shift
A
Asher 已提交
62
	cat "${rootPath}/scripts/nbin-shim.js" "${filePath}" > "${filePath}.temp"
A
Asher 已提交
63 64 65 66
	mv "${filePath}.temp" "${filePath}"
	# Using : as the delimiter so the escaping here is easier to read.
	# ${parameter/pattern/string}, so the pattern is /: (if the pattern starts
	# with / it matches all instances) and the string is \\: (results in \:).
A
Asher 已提交
67 68 69 70 71
	if [[ "${target}" == "darwin" ]] ; then
		sed -i "" -e "s:{{ROOT_PATH}}:${codeServerBuildPath//:/\\:}:g" "${filePath}"
	else
		sed -i "s:{{ROOT_PATH}}:${codeServerBuildPath//:/\\:}:g" "${filePath}"
	fi
A
Asher 已提交
72 73
}

A
Asher 已提交
74 75 76 77 78 79 80 81
# Copy code-server into VS Code then build it.
function build-code-server() {
	copy-server

	# TODO: look into making it do the full minified build for just our code
	# (basically just want to skip extensions, target our server code, and get
	# the same type of build you get with the vscode-linux-x64-min task).
	# Something like: yarn gulp "vscode-server-${target}-${arch}-min"
A
Asher 已提交
82
	log "Building code-server"
A
Asher 已提交
83 84 85 86 87
	yarn gulp compile-client

	rm -rf "${codeServerBuildPath}"
	mkdir -p "${codeServerBuildPath}"

A
Asher 已提交
88 89
	local json="{\"codeServerVersion\": \"${codeServerVersion}\"}"

A
Asher 已提交
90
	cp -r "${vscodeBuildPath}/resources/app/extensions" "${codeServerBuildPath}"
A
Asher 已提交
91
	node "${rootPath}/scripts/merge.js" "${vscodeBuildPath}/resources/app/package.json" "${rootPath}/scripts/package.json" "${codeServerBuildPath}/package.json" "${json}"
A
Asher 已提交
92
	node "${rootPath}/scripts/merge.js" "${vscodeBuildPath}/resources/app/product.json" "${rootPath}/scripts/product.json" "${codeServerBuildPath}/product.json"
A
Asher 已提交
93
	cp -r "${vscodeSourcePath}/out" "${codeServerBuildPath}"
A
Asher 已提交
94 95 96 97 98 99 100 101 102 103
	rm -rf "${codeServerBuildPath}/out/vs/server/typings"

	# Rebuild to make sure the native modules work since at the moment all the
	# pre-built packages are from one Linux system. This means you must build on
	# the target system.
	log "Installing remote dependencies"
	cd "${vscodeSourcePath}/remote"
	if [[ "${target}" != "linux" ]] ; then
		yarn --production --force
	fi
A
Asher 已提交
104 105
	cp -r "${vscodeSourcePath}/remote/node_modules" "${codeServerBuildPath}"

A
Asher 已提交
106 107 108 109
	# Only keep the production dependencies.
	cd "${codeServerBuildPath}/out/vs/server"
	yarn --production --ignore-scripts

A
Asher 已提交
110 111 112
	prepend-loader "out/vs/server/main.js"
	prepend-loader "out/bootstrap-fork.js"

A
Asher 已提交
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
	log "Final build: ${codeServerBuildPath}"
}

# Build VS Code if it hasn't already been built. If we're in the CI and it's
# not fully built, error and exit.
function build-vscode() {
	if [[ ! -d "${vscodeSourcePath}" ]] ; then
		exit-if-ci
		log "${vscodeSourceName} does not exist, cloning"
		git clone https://github.com/microsoft/vscode --quiet \
			--branch "${vscodeVersion}" --single-branch --depth=1 \
			"${vscodeSourcePath}"
	else
		log "${vscodeSourceName} already exists, skipping clone"
	fi

	cd "${vscodeSourcePath}"

	if [[ ! -d "${vscodeSourcePath}/node_modules" ]] ; then
		exit-if-ci
		log "Installing VS Code dependencies"
A
Asher 已提交
134 135 136
		# Not entirely sure why but there seem to be problems with native modules
		# so rebuild them.
		yarn --force
A
Asher 已提交
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164

		# Keep just what we need to keep the pre-built archive smaller.
		rm -rf "${vscodeSourcePath}/test"
	else
		log "${vscodeSourceName}/node_modules already exists, skipping install"
	fi

	if [[ ! -d "${vscodeBuildPath}" ]] ; then
		exit-if-ci
		log "${vscodeBuildName} does not exist, building"
		local builtPath="${buildPath}/VSCode-${target}-${arch}"
		rm -rf "${builtPath}"
		yarn gulp "vscode-${target}-${arch}-min" --max-old-space-size=32384
		mkdir -p "${vscodeBuildPath}/resources/app"
		# Copy just what we need to keep the pre-built archive smaller.
		mv "${builtPath}/resources/app/extensions" "${vscodeBuildPath}/resources/app"
		mv "${builtPath}/resources/app/"*.json "${vscodeBuildPath}/resources/app"
		rm -rf "${builtPath}"
	else
		log "${vscodeBuildName} already exists, skipping build"
	fi
}

# Download VS Code with either curl or wget depending on which is available.
function download-vscode() {
	cd "${buildPath}"
	if command -v wget &> /dev/null ; then
		log "Attempting to download ${tarName} with wget"
A
Asher 已提交
165
		wget "${vsSourceUrl}" --quiet --output-document "${tarName}"
A
Asher 已提交
166 167 168 169 170 171 172 173 174 175 176 177 178
	else
		log "Attempting to download ${tarName} with curl"
		curl "${vsSourceUrl}" --silent --fail --output "${tarName}"
	fi
}

# Download pre-built VS Code if necessary. Build if there is no available
# download but not when in the CI. The pre-built package basically just
# provides us the dependencies and extensions so we don't have to install and
# build them respectively which takes a long time.
function prepare-vscode() {
	if [[ ! -d "${vscodeBuildPath}" || ! -d "${vscodeSourcePath}" ]] ; then
		mkdir -p "${buildPath}"
A
Asher 已提交
179 180
		# TODO: for now everything uses the Linux build and we rebuild the modules.
		# This means you must build on the target system.
A
Asher 已提交
181
		local tarName="vstar-${vscodeVersion}-${target}-${arch}.tar.gz"
A
Asher 已提交
182 183 184
		local linuxTarName="vstar-${vscodeVersion}-linux-${arch}.tar.gz"
		local linuxVscodeBuildName="vscode-${vscodeVersion}-linux-${arch}-built"
		local vsSourceUrl="https://codesrv-ci.cdr.sh/${linuxTarName}"
A
Asher 已提交
185 186 187 188 189
		if download-vscode ; then
			cd "${buildPath}"
			rm -rf "${vscodeBuildPath}"
			tar -xzf "${tarName}"
			rm "${tarName}"
A
Asher 已提交
190 191 192
			if [[ "${target}" != "linux" ]] ; then
				mv "${linuxVscodeBuildName}" "${vscodeBuildName}"
			fi
A
Asher 已提交
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
		elif [[ -n "${ci}" ]] ; then
			log "Pre-built VS Code ${vscodeVersion}-${target}-${arch} does not exist" "error"
			exit 1
		else
			log "${tarName} does not exist, building"
			build-vscode
			return
		fi
	else
		log "VS Code is already downloaded or built"
	fi

	log "Ensuring VS Code is fully built"
	build-vscode
}

function build-task() {
	prepare-vscode
	build-code-server
}

function vstar-task() {
	local archivePath="${releasePath}/vstar-${vscodeVersion}-${target}-${arch}.tar.gz"
	rm -f "${archivePath}"
	mkdir -p "${releasePath}"
	tar -C "${buildPath}" -czf "${archivePath}" "${vscodeSourceName}" "${vscodeBuildName}"
	log "Archive: ${archivePath}"
}

function package-task() {
A
Asher 已提交
223
	local archivePath="${releasePath}/${binaryName}"
A
Asher 已提交
224 225 226
	rm -rf "${archivePath}"
	mkdir -p "${archivePath}"

A
Asher 已提交
227
	cp "${buildPath}/${binaryName}" "${archivePath}/code-server"
A
Asher 已提交
228 229 230 231 232
	cp "${rootPath}/README.md" "${archivePath}"
	cp "${vscodeSourcePath}/LICENSE.txt" "${archivePath}"
	cp "${vscodeSourcePath}/ThirdPartyNotices.txt" "${archivePath}"

	cd "${releasePath}"
A
Asher 已提交
233
	if [[ "${target}" == "darwin" ]] ; then
A
Asher 已提交
234
		zip -r "${binaryName}.zip" "${binaryName}"
A
Asher 已提交
235
		log "Archive: ${archivePath}.zip"
A
Asher 已提交
236 237 238
	else
		tar -czf "${binaryName}.tar.gz" "${binaryName}"
		log "Archive: ${archivePath}.tar.gz"
A
Asher 已提交
239 240 241 242 243 244 245 246 247 248 249 250
	fi
}

# Package built code into a binary.
function binary-task() {
	# I had trouble getting VS Code to build with the @coder/nbin dependency due
	# to the types it installs (tons of conflicts), so for now it's a global
	# dependency.
	cd "${rootPath}"
	npm link @coder/nbin
	node "${rootPath}/scripts/nbin.js" "${target}" "${arch}" "${codeServerBuildPath}"
	rm node_modules/@coder/nbin
A
Asher 已提交
251
	mv "${codeServerBuildPath}/code-server" "${buildPath}/${binaryName}"
A
Asher 已提交
252
	log "Binary: ${buildPath}/${binaryName}"
A
Asher 已提交
253 254
}

A
Asher 已提交
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
# Check if it looks like we are inside VS Code.
function in-vscode () {
	log "Checking if we are inside VS Code"
	local dir="${1}" ; shift

	local maybeVscode
	local dirName
	maybeVscode="$(realpath "${dir}/../../..")"
	dirName="$(basename "${maybeVscode}")"

	if [[ "${dirName}" != "vscode" ]] ; then
		return 1
	fi
	if [[ ! -f "${maybeVscode}/package.json" ]] ; then
		return 1
	fi
	if ! grep '"name": "code-oss-dev"' "${maybeVscode}/package.json" --quiet ; then
		return 1
	fi

	return 0
}

function ensure-in-vscode-task() {
	if ! in-vscode "${rootPath}"; then
		log "Not in vscode" "error"
		exit 1
	fi
	exit 0
}

A
Asher 已提交
286
function main() {
A
Asher 已提交
287 288 289 290 291
	local relativeRootPath
	local rootPath
	relativeRootPath="$(dirname "${0}")/.."
	rootPath="$(realpath "${relativeRootPath}")"

A
Asher 已提交
292
	local task="${1}" ; shift
A
Asher 已提交
293 294 295 296
	if [[ "${task}" == "ensure-in-vscode" ]] ; then
		ensure-in-vscode-task
	fi

A
Asher 已提交
297
	local codeServerVersion="${1}" ; shift
A
Asher 已提交
298 299 300 301 302 303 304 305 306 307
	local vscodeVersion="${1}" ; shift
	local target="${1}" ; shift
	local arch="${1}" ; shift
	local ci="${CI:-}"

	# This lets you build in a separate directory since building within this
	# directory while developing makes it hard to keep developing since compiling
	# will compile everything in the build directory as well.
	local outPath="${OUT:-${rootPath}}"

A
Asher 已提交
308 309
	# If we're inside a vscode directory, assume we want to develop. In that case
	# we should set an OUT directory and not build in this directory.
A
Asher 已提交
310 311 312
	if in-vscode "${outPath}" ; then
		log "Set the OUT environment variable to something outside of VS Code" "error"
		exit 1
A
Asher 已提交
313 314
	fi

A
Asher 已提交
315 316 317 318 319 320 321 322
	local releasePath="${outPath}/release"
	local buildPath="${outPath}/build"

	local vscodeSourceName="vscode-${vscodeVersion}-source"
	local vscodeBuildName="vscode-${vscodeVersion}-${target}-${arch}-built"
	local vscodeSourcePath="${buildPath}/${vscodeSourceName}"
	local vscodeBuildPath="${buildPath}/${vscodeBuildName}"

A
Asher 已提交
323
	local codeServerBuildName="code-server${codeServerVersion}-vsc${vscodeVersion}-${target}-${arch}-built"
A
Asher 已提交
324
	local codeServerBuildPath="${buildPath}/${codeServerBuildName}"
A
Asher 已提交
325
	local binaryName="code-server${codeServerVersion}-vsc${vscodeVersion}-${target}-${arch}"
A
Asher 已提交
326 327 328 329

	log "Running ${task} task"
	log " rootPath: ${rootPath}"
	log " outPath: ${outPath}"
A
Asher 已提交
330
	log " codeServerVersion: ${codeServerVersion}"
A
Asher 已提交
331 332 333 334 335 336 337 338 339 340 341 342 343
	log " vscodeVersion: ${vscodeVersion}"
	log " target: ${target}"
	log " arch: ${arch}"
	if [[ -n "${ci}" ]] ; then
		log " CI: yes"
	else
		log " CI: no"
	fi

	"${task}-task" "$@"
}

main "$@"