2019-02-22 00:55:42 +07:00
|
|
|
import { register, run } from "@coder/runner";
|
|
|
|
import * as fs from "fs";
|
|
|
|
import * as fse from "fs-extra";
|
2019-02-22 05:03:40 +07:00
|
|
|
import * as os from "os";
|
2019-02-22 00:55:42 +07:00
|
|
|
import * as path from "path";
|
|
|
|
import * as zlib from "zlib";
|
2019-04-04 02:24:00 +07:00
|
|
|
import * as https from "https";
|
|
|
|
import * as tar from "tar";
|
2019-02-22 00:55:42 +07:00
|
|
|
|
2019-02-28 11:28:46 +07:00
|
|
|
const isWin = os.platform() === "win32";
|
2019-02-22 00:55:42 +07:00
|
|
|
const libPath = path.join(__dirname, "../lib");
|
|
|
|
const vscodePath = path.join(libPath, "vscode");
|
2019-04-04 02:24:00 +07:00
|
|
|
const defaultExtensionsPath = path.join(libPath, "extensions");
|
2019-02-22 00:55:42 +07:00
|
|
|
const pkgsPath = path.join(__dirname, "../packages");
|
2019-04-13 04:10:45 +07:00
|
|
|
const vscodeVersion = process.env.VSCODE_VERSION || "1.33.1";
|
2019-04-04 02:24:00 +07:00
|
|
|
const vsSourceUrl = `https://codesrv-ci.cdr.sh/vstar-${vscodeVersion}.tar.gz`;
|
2019-02-22 00:55:42 +07:00
|
|
|
|
|
|
|
const buildServerBinary = register("build:server:binary", async (runner) => {
|
|
|
|
await ensureInstalled();
|
|
|
|
await Promise.all([
|
|
|
|
buildBootstrapFork(),
|
|
|
|
buildWeb(),
|
|
|
|
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"))) {
|
2019-02-27 00:07:00 +07:00
|
|
|
throw new Error("Cannot build binary without server bundle built");
|
2019-02-22 00:55:42 +07:00
|
|
|
}
|
|
|
|
await buildServerBinaryCopy();
|
2019-03-27 01:01:25 +07:00
|
|
|
const resp = await runner.execute(isWin ? "npm.cmd" : "npm", ["run", "build:binary"]);
|
2019-02-22 00:55:42 +07:00
|
|
|
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"));
|
2019-02-27 00:07:00 +07:00
|
|
|
const bootstrapForkPath = path.join(pkgsPath, "vscode", "out", "bootstrap-fork.js");
|
2019-02-22 00:55:42 +07:00
|
|
|
const webOutputPath = path.join(pkgsPath, "web", "out");
|
|
|
|
const browserAppOutputPath = path.join(pkgsPath, "app", "browser", "out");
|
2019-02-28 04:12:26 +07:00
|
|
|
let ripgrepPath = path.join(pkgsPath, "..", "lib", "vscode", "node_modules", "vscode-ripgrep", "bin", "rg");
|
2019-02-28 11:28:46 +07:00
|
|
|
if (isWin) {
|
2019-02-28 04:12:26 +07:00
|
|
|
ripgrepPath += ".exe";
|
|
|
|
}
|
2019-02-22 00:55:42 +07:00
|
|
|
|
|
|
|
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");
|
|
|
|
}
|
2019-02-28 04:12:26 +07:00
|
|
|
if (!fs.existsSync(ripgrepPath)) {
|
|
|
|
throw new Error("Ripgrep must exist");
|
|
|
|
}
|
2019-02-22 00:55:42 +07:00
|
|
|
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);
|
2019-02-28 04:12:26 +07:00
|
|
|
fse.mkdirpSync(path.join(cliBuildPath, "dependencies"));
|
|
|
|
fse.copySync(ripgrepPath, path.join(cliBuildPath, "dependencies", "rg"));
|
2019-02-22 00:55:42 +07:00
|
|
|
});
|
|
|
|
|
|
|
|
const buildServerBundle = register("build:server:bundle", async (runner) => {
|
|
|
|
const cliPath = path.join(pkgsPath, "server");
|
|
|
|
runner.cwd = cliPath;
|
2019-03-01 03:04:19 +07:00
|
|
|
await runner.execute(isWin ? "npm.cmd" : "npm", ["run", "build"]);
|
2019-02-22 00:55:42 +07:00
|
|
|
});
|
|
|
|
|
|
|
|
const buildBootstrapFork = register("build:bootstrap-fork", async (runner) => {
|
|
|
|
await ensureInstalled();
|
|
|
|
await ensurePatched();
|
|
|
|
|
|
|
|
const vscodePkgPath = path.join(pkgsPath, "vscode");
|
|
|
|
runner.cwd = vscodePkgPath;
|
2019-03-01 03:04:19 +07:00
|
|
|
await runner.execute(isWin ? "npm.cmd" : "npm", ["run", "build:bootstrap-fork"]);
|
2019-02-22 00:55:42 +07:00
|
|
|
});
|
|
|
|
|
|
|
|
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"));
|
2019-03-01 03:04:19 +07:00
|
|
|
await runner.execute(isWin ? "npm.cmd" : "npm", ["run", "build"]);
|
2019-02-22 00:55:42 +07:00
|
|
|
});
|
|
|
|
|
|
|
|
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"));
|
2019-03-01 03:04:19 +07:00
|
|
|
await runner.execute(isWin ? "npm.cmd" : "npm", ["run", "build"]);
|
2019-02-22 00:55:42 +07:00
|
|
|
});
|
|
|
|
|
|
|
|
const ensureInstalled = register("vscode:install", async (runner) => {
|
2019-04-04 02:24:00 +07:00
|
|
|
runner.cwd = libPath;
|
2019-02-22 00:55:42 +07:00
|
|
|
|
2019-04-04 02:24:00 +07:00
|
|
|
if (fs.existsSync(vscodePath) && fs.existsSync(defaultExtensionsPath)) {
|
|
|
|
const pkgVersion = JSON.parse(fs.readFileSync(path.join(vscodePath, "package.json")).toString("utf8")).version;
|
|
|
|
if (pkgVersion === vscodeVersion) {
|
|
|
|
runner.cwd = vscodePath;
|
|
|
|
|
|
|
|
const reset = await runner.execute("git", ["reset", "--hard"]);
|
|
|
|
if (reset.exitCode !== 0) {
|
|
|
|
throw new Error(`Failed to clean git repository: ${reset.stderr}`);
|
|
|
|
}
|
2019-02-22 00:55:42 +07:00
|
|
|
|
2019-04-04 02:24:00 +07:00
|
|
|
return;
|
2019-02-22 00:55:42 +07:00
|
|
|
}
|
|
|
|
}
|
2019-03-11 21:47:41 +07:00
|
|
|
|
2019-04-04 02:24:00 +07:00
|
|
|
fse.removeSync(libPath);
|
|
|
|
fse.mkdirpSync(libPath);
|
2019-02-22 00:55:42 +07:00
|
|
|
|
2019-04-04 02:24:00 +07:00
|
|
|
await new Promise<void>((resolve, reject): void => {
|
|
|
|
https.get(vsSourceUrl, (res) => {
|
|
|
|
if (res.statusCode !== 200) {
|
|
|
|
return reject(res.statusMessage);
|
|
|
|
}
|
2019-02-22 00:55:42 +07:00
|
|
|
|
2019-04-04 02:24:00 +07:00
|
|
|
res.pipe(tar.x({
|
|
|
|
C: libPath,
|
|
|
|
}).on("finish", () => {
|
|
|
|
resolve();
|
|
|
|
}).on("error", (err: Error) => {
|
|
|
|
reject(err);
|
|
|
|
}));
|
|
|
|
}).on("error", (err) => {
|
|
|
|
reject(err);
|
|
|
|
});
|
|
|
|
});
|
2019-02-22 00:55:42 +07:00
|
|
|
});
|
|
|
|
|
|
|
|
const ensurePatched = register("vscode:patch", async (runner) => {
|
|
|
|
if (!fs.existsSync(vscodePath)) {
|
|
|
|
throw new Error("vscode must be cloned to patch");
|
|
|
|
}
|
2019-04-04 02:24:00 +07:00
|
|
|
await ensureInstalled();
|
2019-02-22 00:55:42 +07:00
|
|
|
|
|
|
|
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}`);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2019-03-07 07:15:52 +07:00
|
|
|
register("package", async (runner, releaseTag) => {
|
|
|
|
if (!releaseTag) {
|
|
|
|
throw new Error("Please specify the release tag.");
|
|
|
|
}
|
|
|
|
|
|
|
|
const releasePath = path.resolve(__dirname, "../release");
|
|
|
|
|
2019-03-27 01:38:38 +07:00
|
|
|
const archiveName = `code-server${releaseTag}-${os.platform()}-${os.arch()}`;
|
2019-03-07 07:15:52 +07:00
|
|
|
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 binaryDestination = path.join(archiveDir, "code-server");
|
|
|
|
fse.copySync(binaryPath, binaryDestination);
|
|
|
|
fs.chmodSync(binaryDestination, "755");
|
|
|
|
["README.md", "LICENSE"].forEach((fileName) => {
|
|
|
|
fse.copySync(path.resolve(__dirname, `../${fileName}`), path.join(archiveDir, fileName));
|
|
|
|
});
|
|
|
|
|
|
|
|
runner.cwd = releasePath;
|
2019-04-16 07:48:12 +07:00
|
|
|
await (os.platform() === "linux"
|
2019-03-07 07:15:52 +07:00
|
|
|
? runner.execute("tar", ["-cvzf", `${archiveName}.tar.gz`, `${archiveName}`])
|
2019-04-16 07:48:12 +07:00
|
|
|
: runner.execute("zip", ["-r", `${archiveName}.zip`, `${archiveName}`]));
|
2019-03-07 07:15:52 +07:00
|
|
|
});
|
|
|
|
|
2019-02-22 00:55:42 +07:00
|
|
|
run();
|