diff --git a/.travis.yml b/.travis.yml index 5caa76686..4cf5f487b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,12 @@ matrix: include: - os: linux dist: trusty + env: + - TARGET="centos" + - os: linux + dist: trusty + env: + - TARGET="alpine" - os: osx before_install: - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install libxkbfile-dev diff --git a/build/platform.ts b/build/platform.ts new file mode 100644 index 000000000..55f8b7552 --- /dev/null +++ b/build/platform.ts @@ -0,0 +1,42 @@ +/** + * Script that detects platform name and arch. + * Cannot use os.platform() as that won't detect libc version + */ +import * as cp from "child_process"; +import * as fs from "fs"; +import * as os from "os"; + +enum Lib { + GLIBC, + MUSL, +} + +const CLIB: Lib | undefined = ((): Lib | undefined => { + if (os.platform() !== "linux") { + return; + } + const glibc = cp.spawnSync("getconf", ["GNU_LIBC_VERSION"]); + if (glibc.status === 0) { + return Lib.GLIBC; + } + + const ldd = cp.spawnSync("ldd", ["--version"]); + if (ldd.stdout && ldd.stdout.indexOf("musl") !== -1) { + return Lib.MUSL; + } + + const muslFile = fs.readdirSync("/lib").find((value) => value.startsWith("libc.musl")); + if (muslFile) { + return Lib.MUSL; + } + + return Lib.GLIBC; +})(); + +export const platform = (): NodeJS.Platform | "musl" => { + if (CLIB === Lib.MUSL) { + return "musl"; + } + + return os.platform(); +}; diff --git a/build/tasks.ts b/build/tasks.ts index 06199fa82..45d171cf1 100644 --- a/build/tasks.ts +++ b/build/tasks.ts @@ -2,6 +2,7 @@ import { register, run } from "@coder/runner"; import * as fs from "fs"; import * as fse from "fs-extra"; import * as os from "os"; +import { platform } from "./platform"; import * as path from "path"; import * as zlib from "zlib"; import * as https from "https"; @@ -180,12 +181,12 @@ register("package", async (runner, releaseTag) => { const releasePath = path.resolve(__dirname, "../release"); - const archiveName = `code-server${releaseTag}-${os.platform()}-${os.arch()}`; + const archiveName = `code-server${releaseTag}-${platform()}-${os.arch()}`; const archiveDir = path.join(releasePath, archiveName); fse.removeSync(archiveDir); fse.mkdirpSync(archiveDir); - const binaryPath = path.join(__dirname, `../packages/server/cli-${os.platform()}-${os.arch()}`); + const binaryPath = path.join(__dirname, `../packages/server/cli-${platform()}-${os.arch()}`); const binaryDestination = path.join(archiveDir, "code-server"); fse.copySync(binaryPath, binaryDestination); fs.chmodSync(binaryDestination, "755"); diff --git a/packages/server/scripts/nbin.ts b/packages/server/scripts/nbin.ts index ae3674b8a..bbc76ba13 100644 --- a/packages/server/scripts/nbin.ts +++ b/packages/server/scripts/nbin.ts @@ -2,11 +2,13 @@ import { Binary } from "@coder/nbin"; import * as fs from "fs"; import * as os from "os"; import * as path from "path"; +import { platform } from "../../../build/platform"; -const target = `${os.platform()}-${os.arch()}`; +const target = `${platform()}-${os.arch()}`; const rootDir = path.join(__dirname, ".."); const bin = new Binary({ mainFile: path.join(rootDir, "out", "cli.js"), + target: platform() === "darwin" ? "darwin" : platform() === "musl" ? "alpine" : "linux", }); bin.writeFiles(path.join(rootDir, "build", "**")); bin.writeFiles(path.join(rootDir, "out", "**")); diff --git a/scripts/build.sh b/scripts/build.sh index 3d954fee6..2c7c0dff2 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -1,4 +1,32 @@ #!/bin/bash -set -e +set -euxo pipefail -yarn task build:server:binary +# Variables to be set: +# $IMAGE +function docker_build() { + containerID=$(docker create -it -v $(pwd)/.cache:/src/.cache $IMAGE) + docker start $containerID + docker exec $containerID mkdir -p /src + + function exec() { + docker exec $containerID bash -c "$@" + } + + docker cp ./. $containerID:/src + exec "cd /src && yarn" + exec "cd /src && npm rebuild" + exec "cd /src && yarn task build:server:binary" + exec "cd /src && yarn task package $VERSION" + docker cp $containerID:/src/release/. ./release/ +} + +if [[ "$OSTYPE" == "darwin"* ]]; then + yarn task build:server:binary +else + if [[ "$TARGET" == "alpine" ]]; then + IMAGE="codercom/nbin-alpine" + else + IMAGE="codercom/nbin-centos" + fi + docker_build +fi