code-server/build/tasks.ts
Kyle Carberry 85d2225e0c Featureful (#31)
* Fix loading within the CLI

* Remove app

* Remove promise handle

* Add initial travis file

* Add libxkbfile dependency

* Add libxkbfile-dev

* Add build script

* Fix malformed bash statement

* Remove yarn from script

* Improve build script

* Extract upx before usage

* Only run upx if on linux

* Ensure resource directory exists

* Pack runnable binary

* Export binary with platform

* Improve build process

* Install upx before running install script

* Update typescript version before running nexe

* Add os.release() function for multi-platform support

* Update travis.yml to improve deployment

* Add on CI

* Update to v1.31.0

* Add libsecret

* Update build target

* Skip cleanup

* Fix built-in extensions

* Add basics for apps

* Create custom DNS server

* Fix forking within CLI. Fixes TS language features

* Fix filename resolve

* Fix default extensions path

* Add custom dialog

* Store workspace path

* Remove outfiles

* Cleanup

* Always authed outside of CLI

* Use location.host for client

* Remove useless app interface

* Remove debug file for building wordlist

* Use chromes tcp host

* Update patch

* Build browser app before packaging

* Replace all css containing file:// URLs, fix webviews

* Fix save

* Fix mkdir
2019-02-21 11:55:42 -06:00

196 lines
6.7 KiB
TypeScript

import { register, run } from "@coder/runner";
import * as fs from "fs";
import * as fse from "fs-extra";
import * as path from "path";
import * as zlib from "zlib";
const libPath = path.join(__dirname, "../lib");
const vscodePath = path.join(libPath, "vscode");
const pkgsPath = path.join(__dirname, "../packages");
const defaultExtensionsPath = path.join(libPath, "VSCode-linux-x64/resources/app/extensions");
const buildServerBinary = register("build:server:binary", async (runner) => {
await ensureInstalled();
await copyForDefaultExtensions();
await Promise.all([
buildBootstrapFork(),
buildWeb(),
buildDefaultExtensions(),
buildServerBundle(),
buildAppBrowser(),
]);
await buildServerBinaryPackage();
});
const buildServerBinaryPackage = register("build:server:binary:package", async (runner) => {
const cliPath = path.join(pkgsPath, "server");
runner.cwd = cliPath;
if (!fs.existsSync(path.join(cliPath, "out"))) {
throw new Error("Cannot build binary without web bundle built");
}
await buildServerBinaryCopy();
const resp = await runner.execute("npm", ["run", "build:nexe"]);
if (resp.exitCode !== 0) {
throw new Error(`Failed to package binary: ${resp.stderr}`);
}
});
const buildServerBinaryCopy = register("build:server:binary:copy", async (runner) => {
const cliPath = path.join(pkgsPath, "server");
const cliBuildPath = path.join(cliPath, "build");
fse.removeSync(cliBuildPath);
fse.mkdirpSync(path.join(cliBuildPath, "extensions"));
const bootstrapForkPath = path.join(pkgsPath, "vscode", "bin", "bootstrap-fork.js");
const webOutputPath = path.join(pkgsPath, "web", "out");
const browserAppOutputPath = path.join(pkgsPath, "app", "browser", "out");
const nodePtyModule = path.join(pkgsPath, "protocol", "node_modules", "node-pty", "build", "Release", "pty.node");
if (!fs.existsSync(nodePtyModule)) {
throw new Error("Could not find pty.node. Ensure all packages have been installed");
}
if (!fs.existsSync(webOutputPath)) {
throw new Error("Web bundle must be built");
}
if (!fs.existsSync(defaultExtensionsPath)) {
throw new Error("Default extensions must be built");
}
if (!fs.existsSync(bootstrapForkPath)) {
throw new Error("Bootstrap fork must exist");
}
fse.copySync(defaultExtensionsPath, path.join(cliBuildPath, "extensions"));
fs.writeFileSync(path.join(cliBuildPath, "bootstrap-fork.js.gz"), zlib.gzipSync(fs.readFileSync(bootstrapForkPath)));
const cpDir = (dir: string, subdir: "auth" | "unauth", rootPath: string): void => {
const stat = fs.statSync(dir);
if (stat.isDirectory()) {
const paths = fs.readdirSync(dir);
paths.forEach((p) => cpDir(path.join(dir, p), subdir, rootPath));
} else if (stat.isFile()) {
const newPath = path.join(cliBuildPath, "web", subdir, path.relative(rootPath, dir));
fse.mkdirpSync(path.dirname(newPath));
fs.writeFileSync(newPath + ".gz", zlib.gzipSync(fs.readFileSync(dir)));
} else {
// Nothing
}
};
cpDir(webOutputPath, "auth", webOutputPath);
cpDir(browserAppOutputPath, "unauth", browserAppOutputPath);
fse.mkdirpSync(path.join(cliBuildPath, "modules"));
fse.copySync(nodePtyModule, path.join(cliBuildPath, "modules", "pty.node"));
});
const buildServerBundle = register("build:server:bundle", async (runner) => {
const cliPath = path.join(pkgsPath, "server");
runner.cwd = cliPath;
await runner.execute("npm", ["run", "build:webpack"]);
});
const buildBootstrapFork = register("build:bootstrap-fork", async (runner) => {
await ensureInstalled();
await ensurePatched();
const vscodePkgPath = path.join(pkgsPath, "vscode");
runner.cwd = vscodePkgPath;
await runner.execute("npm", ["run", "build:bootstrap-fork"]);
});
const buildAppBrowser = register("build:app:browser", async (runner) => {
await ensureInstalled();
const appPath = path.join(pkgsPath, "app/browser");
runner.cwd = appPath;
fse.removeSync(path.join(appPath, "out"));
await runner.execute("npm", ["run", "build"]);
});
const buildWeb = register("build:web", async (runner) => {
await ensureInstalled();
await ensurePatched();
const webPath = path.join(pkgsPath, "web");
runner.cwd = webPath;
fse.removeSync(path.join(webPath, "out"));
await runner.execute("npm", ["run", "build"]);
});
const extDirPath = path.join("lib", "vscode-default-extensions");
const copyForDefaultExtensions = register("build:copy-vscode", async (runner) => {
if (!fs.existsSync(defaultExtensionsPath)) {
await ensureClean();
fse.removeSync(extDirPath);
fse.copySync(vscodePath, extDirPath);
}
});
const buildDefaultExtensions = register("build:default-extensions", async (runner) => {
if (!fs.existsSync(defaultExtensionsPath)) {
await copyForDefaultExtensions();
runner.cwd = extDirPath;
const resp = await runner.execute("npx", ["gulp", "vscode-linux-x64"]);
if (resp.exitCode !== 0) {
throw new Error(`Failed to build default extensions: ${resp.stderr}`);
}
}
});
const ensureInstalled = register("vscode:install", async (runner) => {
await ensureCloned();
runner.cwd = vscodePath;
const install = await runner.execute("yarn", []);
if (install.exitCode !== 0) {
throw new Error(`Failed to install vscode dependencies: ${install.stderr}`);
}
});
const ensureCloned = register("vscode:clone", async (runner) => {
if (fs.existsSync(vscodePath)) {
await ensureClean();
} else {
fs.mkdirSync(libPath);
runner.cwd = libPath;
const clone = await runner.execute("git", ["clone", "https://github.com/microsoft/vscode"]);
if (clone.exitCode !== 0) {
throw new Error(`Failed to clone: ${clone.exitCode}`);
}
}
runner.cwd = vscodePath;
const checkout = await runner.execute("git", ["checkout", "tags/1.31.0"]);
if (checkout.exitCode !== 0) {
throw new Error(`Failed to checkout: ${checkout.stderr}`);
}
});
const ensureClean = register("vscode:clean", async (runner) => {
runner.cwd = vscodePath;
const status = await runner.execute("git", ["status", "--porcelain"]);
if (status.stdout.trim() !== "") {
const clean = await runner.execute("git", ["clean", "-f", "-d", "-X"]);
if (clean.exitCode !== 0) {
throw new Error(`Failed to clean git repository: ${clean.stderr}`);
}
const removeUnstaged = await runner.execute("git", ["checkout", "--", "."]);
if (removeUnstaged.exitCode !== 0) {
throw new Error(`Failed to remove unstaged files: ${removeUnstaged.stderr}`);
}
}
});
const ensurePatched = register("vscode:patch", async (runner) => {
if (!fs.existsSync(vscodePath)) {
throw new Error("vscode must be cloned to patch");
}
await ensureClean();
runner.cwd = vscodePath;
const patchPath = path.join(__dirname, "../scripts/vscode.patch");
const apply = await runner.execute("git", ["apply", "--unidiff-zero", patchPath]);
if (apply.exitCode !== 0) {
throw new Error(`Failed to apply patches: ${apply.stderr}`);
}
});
run();