Archived
1
0

Switch to loose files

For #1306.
This commit is contained in:
Asher
2020-02-25 16:20:47 -06:00
parent f76c809f7d
commit c870398c86
13 changed files with 138 additions and 773 deletions

View File

@ -1,14 +1,10 @@
import { Binary } from "@coder/nbin"
import * as cp from "child_process"
import * as fs from "fs-extra"
import * as os from "os"
import Bundler from "parcel-bundler"
import * as path from "path"
import * as util from "util"
enum Task {
Binary = "binary",
Package = "package",
Build = "build",
Watch = "watch",
}
@ -16,10 +12,8 @@ enum Task {
class Builder {
private readonly rootPath = path.resolve(__dirname, "..")
private readonly vscodeSourcePath = path.join(this.rootPath, "lib/vscode")
private readonly binariesPath = path.join(this.rootPath, "binaries")
private readonly buildPath = path.join(this.rootPath, "build")
private readonly codeServerVersion: string
private _target?: "darwin" | "alpine" | "linux"
private currentTask?: Task
public constructor() {
@ -66,17 +60,9 @@ class Builder {
throw new Error("No task provided")
}
const arch = this.ensureArgument("arch", os.arch().replace(/^x/, "x86_"))
const target = this.ensureArgument("target", await this.target())
const binaryName = `code-server-${this.codeServerVersion}-${target}-${arch}`
switch (task) {
case Task.Watch:
return this.watch()
case Task.Binary:
return this.binary(binaryName)
case Task.Package:
return this.package(binaryName)
case Task.Build:
return this.build()
default:
@ -84,29 +70,6 @@ class Builder {
}
}
/**
* Get the target of the system.
*/
private async target(): Promise<"darwin" | "alpine" | "linux"> {
if (!this._target) {
if (os.platform() === "darwin" || (process.env.OSTYPE && /^darwin/.test(process.env.OSTYPE))) {
this._target = "darwin"
} else {
// Alpine's ldd doesn't have a version flag but if you use an invalid flag
// (like --version) it outputs the version to stderr and exits with 1.
const result = await util
.promisify(cp.exec)("ldd --version")
.catch((error) => ({ stderr: error.message, stdout: "" }))
if (/musl/.test(result.stderr) || /musl/.test(result.stdout)) {
this._target = "alpine"
} else {
this._target = "linux"
}
}
}
return this._target
}
/**
* Make sure the argument is set. Display the value if it is.
*/
@ -256,114 +219,6 @@ class Builder {
}
}
/**
* Bundles the built code into a binary.
*/
private async binary(binaryName: string): Promise<void> {
const prependCode = async (code: string, relativeFilePath: string): Promise<void> => {
const filePath = path.join(this.buildPath, relativeFilePath)
const content = await fs.readFile(filePath, "utf8")
if (!content.startsWith(code)) {
await fs.writeFile(filePath, code + content)
}
}
// Unpack binaries since we can't run them within the binary.
const unpack = `
if (global.NBIN_LOADED) {
try {
const fs = require("fs-extra")
const rg = require("vscode-ripgrep")
const path = require("path")
const { logger, field } = require("@coder/logger")
const unpackExecutables = async (filePath, destination) => {
logger.debug("unpacking executable", field("src", filePath), field("dest", destination))
await fs.mkdirp(path.dirname(destination))
if (filePath && !(await fs.pathExists(destination))) {
await fs.writeFile(destination, await fs.readFile(filePath))
await fs.chmod(destination, "755")
}
}
unpackExecutables(rg.binaryRgPath, rg.rgPath).catch((error) => console.warn(error))
} catch (error) {
console.warn(error)
}
}
`
// Enable finding files within the binary.
const loader = `
if (!global.NBIN_LOADED) {
try {
const nbin = require("nbin")
nbin.shimNativeFs("${this.buildPath}")
global.NBIN_LOADED = true
require("@coder/logger").logger.debug("shimmed file system at ${this.buildPath}")
const path = require("path")
const rg = require("vscode-ripgrep")
rg.binaryRgPath = rg.rgPath
rg.rgPath = path.join(require("os").tmpdir(), "code-server/binaries", path.basename(rg.binaryRgPath))
} catch (error) {
// Most likely not in the binary.
}
}
`
await this.task("Prepending nbin loader", () => {
return Promise.all([
prependCode(loader, "out/node/entry.js"),
prependCode(loader, "lib/vscode/out/vs/server/entry.js"),
prependCode(loader + unpack, "lib/vscode/out/vs/server/fork.js"),
prependCode(loader, "lib/vscode/out/bootstrap-fork.js"),
prependCode(loader, "lib/vscode/extensions/node_modules/typescript/lib/tsserver.js"),
])
})
const bin = new Binary({
mainFile: path.join(this.buildPath, "out/node/entry.js"),
target: await this.target(),
})
bin.writeFiles(path.join(this.buildPath, "**"))
await fs.mkdirp(this.binariesPath)
const binaryPath = path.join(this.binariesPath, binaryName)
await fs.writeFile(binaryPath, await bin.build())
await fs.chmod(binaryPath, "755")
this.log(`binary: ${binaryPath}`)
}
/**
* Package the binary into a release archive.
*/
private async package(binaryName: string): Promise<void> {
const releasePath = path.join(this.rootPath, "release")
const archivePath = path.join(releasePath, binaryName)
await fs.remove(archivePath)
await fs.mkdirp(archivePath)
await fs.copyFile(path.join(this.binariesPath, binaryName), path.join(archivePath, "code-server"))
await fs.copyFile(path.join(this.rootPath, "README.md"), path.join(archivePath, "README.md"))
await fs.copyFile(path.join(this.vscodeSourcePath, "LICENSE.txt"), path.join(archivePath, "LICENSE.txt"))
await fs.copyFile(
path.join(this.vscodeSourcePath, "ThirdPartyNotices.txt"),
path.join(archivePath, "ThirdPartyNotices.txt"),
)
if ((await this.target()) === "darwin") {
await util.promisify(cp.exec)(`zip -r "${binaryName}.zip" "${binaryName}"`, { cwd: releasePath })
this.log(`archive: ${archivePath}.zip`)
} else {
await util.promisify(cp.exec)(`tar -czf "${binaryName}.tar.gz" "${binaryName}"`, { cwd: releasePath })
this.log(`archive: ${archivePath}.tar.gz`)
}
}
private async watch(): Promise<void> {
let server: cp.ChildProcess | undefined
const restartServer = (): void => {

6
ci/code-server.sh Executable file
View File

@ -0,0 +1,6 @@
#!/usr/bin/env sh
# code-server.sh -- Run code-server with the bundled Node binary.
cd "$(dirname "$0")" || exit 1
./node ./out/node/entry.js "$@"

View File

@ -16,7 +16,7 @@ RUN apt-get install -y dumb-init sudo
RUN apt-get install -y man procps vim nano htop ssh git
RUN adduser --gecos '' --disabled-password coder && \
echo "coder ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/nopasswd
echo "coder ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/nopasswd
RUN curl -SsL https://github.com/boxboat/fixuid/releases/download/v0.4/fixuid-0.4-linux-amd64.tar.gz | tar -C /usr/local/bin -xzf - && \
chown root:root /usr/local/bin/fixuid && \
@ -27,11 +27,12 @@ RUN curl -SsL https://github.com/boxboat/fixuid/releases/download/v0.4/fixuid-0.
RUN rm -rf /var/lib/apt/lists/*
COPY release/code-server*.tar.gz /tmp
RUN cd /tmp && tar -xzf code-server*.tar.gz && \
cp code-server*/code-server /usr/local/bin/code-server
RUN rm -rf /tmp/*
RUN cd /tmp && tar -xzf code-server*.tar.gz && rm code-server*.tar.gz && \
mv code-server* /usr/local/lib/code-server && \
sed 's/\$0/\/usr\/local\/lib\/code-server\/code-server/g' /usr/local/lib/code-server/code-server > /usr/local/bin/code-server && \
chmod +x /usr/local/bin/code-server
EXPOSE 8080
USER coder
WORKDIR /home/coder
ENTRYPOINT ["dumb-init", "fixuid", "-q", "code-server", "--host", "0.0.0.0", "."]
ENTRYPOINT ["dumb-init", "fixuid", "-q", "/usr/local/bin/code-server", "--host", "0.0.0.0", "."]

View File

@ -3,52 +3,72 @@
set -euo pipefail
function package() {
local target
target=$(uname | tr '[:upper:]' '[:lower:]')
if [[ $target == "linux" ]]; then
# Alpine's ldd doesn't have a version flag but if you use an invalid flag
# (like --version) it outputs the version to stderr and exits with 1.
local ldd_output
ldd_output=$(ldd --version 2>&1 || true)
if echo "$ldd_output" | grep -iq musl; then
target="alpine"
fi
fi
local arch
arch="$(uname -m)"
echo -n "Creating release..."
cp "$(command -v node)" ./build
cp README.md ./build
cp LICENSE.txt ./build
cp ./lib/vscode/ThirdPartyNotices.txt ./build
cp ./ci/code-server.sh ./build/code-server
local archive_name="code-server-$VERSION-$target-$arch"
mkdir -p ./release
local ext
if [[ $target == "linux" ]]; then
ext=".tar.gz"
tar -czf "release/$archive_name$ext" --transform "s/^\.\/build/$archive_name/" ./build
else
mv ./build "./$archive_name"
ext=".zip"
zip -r "release/$archive_name$ext" ./code-server
mv "./$archive_name" ./build
fi
echo "done (release/$archive_name)"
mkdir -p "./release-upload/$VERSION"
cp "./release/$archive_name$ext" "./release-upload/$VERSION/$target-$arch.tar.gz"
mkdir -p "./release-upload/latest"
cp "./release/$archive_name$ext" "./release-upload/latest/$target-$arch.tar.gz"
}
# This script assumes that yarn has already ran.
function build() {
# Always minify and package on CI.
if [[ ${CI:-} ]]; then
export MINIFY="true"
fi
yarn build
}
function main() {
cd "$(dirname "${0}")/.."
source ./ci/lib.sh
set_version
# Always minify and package on CI since that's when releases are pushed.
build
if [[ ${CI:-} ]]; then
export MINIFY="true"
export PACKAGE="true"
fi
yarn build
yarn binary
if [[ -n ${PACKAGE:-} ]]; then
yarn package
fi
cd binaries
if [[ -n ${STRIP_BIN_TARGET:-} ]]; then
# In this case provide plainly named binaries.
for binary in code-server*; do
echo "Moving $binary to code-server"
mv "$binary" code-server
done
elif [[ -n ${DRONE_TAG:-} || -n ${TRAVIS_TAG:-} ]]; then
# Prepare directory for uploading binaries on release.
for binary in code-server*; do
mkdir -p "../binary-upload"
local prefix="code-server-$VERSION-"
local target="${binary#$prefix}"
if [[ $target == "linux-x86_64" ]]; then
echo "Copying $binary to ../binary-upload/latest-linux"
cp "$binary" "../binary-upload/latest-linux"
fi
local gcp_dir
gcp_dir="../binary-upload/releases/$VERSION/$target"
mkdir -p "$gcp_dir"
echo "Copying $binary to $gcp_dir/code-server"
cp "$binary" "$gcp_dir/code-server"
done
package
fi
}

View File

@ -179,22 +179,6 @@ index 5a631e0b39..4114bd9287 100644
} else if (typeof process === 'object') {
_isWindows = (process.platform === 'win32');
_isMacintosh = (process.platform === 'darwin');
diff --git a/src/vs/base/common/processes.ts b/src/vs/base/common/processes.ts
index c52f7b3774..967943d27b 100644
--- a/src/vs/base/common/processes.ts
+++ b/src/vs/base/common/processes.ts
@@ -110,7 +110,10 @@ export function sanitizeProcessEnvironment(env: IProcessEnvironment, ...preserve
/^ELECTRON_.+$/,
/^GOOGLE_API_KEY$/,
/^VSCODE_.+$/,
- /^SNAP(|_.*)$/
+ /^SNAP(|_.*)$/,
+ // NOTE@coder: Add our variables.
+ /^NBIN_BYPASS$/,
+ /^LAUNCH_VSCODE$/
];
const envKeys = Object.keys(env);
envKeys
diff --git a/src/vs/base/node/languagePacks.js b/src/vs/base/node/languagePacks.js
index 2c64061da7..c0ef8faedd 100644
--- a/src/vs/base/node/languagePacks.js