未验证 提交 4cd2f2cd 编写于 作者: A Asher

Simplify build and development steps

上级 88cef85f
......@@ -58,17 +58,13 @@ arguments when launching code-server with Docker. See
### Build
- If you also plan on developing, set the `OUT` environment variable. Otherwise
it will build in this directory which will cause issues because `yarn watch`
will try to compile the build directory as well.
- Run `yarn build ${vscodeVersion} ${codeServerVersion}` in this directory (for
example: `yarn build 1.36.0 development`).
- If you target the same VS Code version our Travis builds do everything will
work but if you target some other version it might not (we have to do some
patching to VS Code so different versions aren't always compatible).
- You can run the built code with `node path/to/build/out/vs/server/main.js` or run
`yarn binary` with the same arguments in the previous step to package the
code into a single binary.
```shell
export OUT=/path/to/output/build # Optional if only building. Required if also developing.
yarn build ${vscodeVersion} ${codeServerVersion} # See travis.yml for the VS Code version to use.
# The code-server version can be anything you want.
node ~/path/to/output/build/out/vs/server/main.js # You can run the built JavaScript with Node.
yarn binary ${vscodeVersion} ${codeServerVersion} # Or you can package it into a binary.
```
## Known Issues
......@@ -109,11 +105,12 @@ data collected to improve code-server.
```shell
git clone https://github.com/microsoft/vscode
cd vscode
git checkout <see travis.yml for the VS Code version to use here>
git checkout ${vscodeVersion} # See travis.yml for the version to use.
yarn
git clone https://github.com/cdr/code-server src/vs/server
cd src/vs/server
yarn patch:apply
yarn
yarn patch:apply
yarn watch
# Wait for the initial compilation to complete (it will say "Finished compilation").
# Run the next command in another shell.
......
......@@ -2,15 +2,13 @@
"license": "MIT",
"scripts": {
"runner": "cd ./scripts && node --max-old-space-size=32384 -r ts-node/register ./build.ts",
"preinstall": "yarn runner ensure-in-vscode && cd ../../../ && yarn || true",
"postinstall": "rm -rf node_modules/@types/node",
"start": "yarn runner ensure-in-vscode && nodemon --watch ../../../out --verbose ../../../out/vs/server/main.js",
"watch": "yarn runner ensure-in-vscode && cd ../../../ && yarn watch",
"build": "yarn --ignore-scripts && yarn runner build",
"start": "nodemon --watch ../../../out --verbose ../../../out/vs/server/main.js",
"watch": "cd ../../../ && yarn watch",
"build": "yarn && yarn runner build",
"package": "yarn runner package",
"binary": "yarn runner binary",
"patch:generate": "yarn runner ensure-in-vscode && cd ../../../ && git diff --staged > ./src/vs/server/scripts/vscode.patch",
"patch:apply": "yarn runner ensure-in-vscode && cd ../../../ && git apply ./src/vs/server/scripts/vscode.patch"
"patch:generate": "cd ../../../ && git diff --staged > ./src/vs/server/scripts/vscode.patch",
"patch:apply": "cd ../../../ && git apply ./src/vs/server/scripts/vscode.patch"
},
"devDependencies": {
"@coder/nbin": "^1.2.2",
......
......@@ -20,21 +20,34 @@ class Builder {
private readonly rootPath = path.resolve(__dirname, "..");
private readonly outPath = process.env.OUT || this.rootPath;
private _target?: "darwin" | "alpine" | "linux";
private task?: Task;
private currentTask?: Task;
public run(task: Task | undefined, args: string[]): void {
this.task = task;
this.currentTask = task;
this.doRun(task, args).catch((error) => {
console.error(error.message);
process.exit(1);
});
}
private async task<T>(message: string, fn: () => Promise<T>): Promise<T> {
const time = Date.now();
this.log(`${message}...`, true);
try {
const t = await fn();
process.stdout.write(`took ${Date.now() - time}ms\n`);
return t;
} catch (error) {
process.stdout.write("failed\n");
throw error;
}
}
/**
* Writes to stdout with an optional newline.
*/
private log(message: string, skipNewline: boolean = false): void {
process.stdout.write(`[${this.task || "default"}] ${message}`);
process.stdout.write(`[${this.currentTask || "default"}] ${message}`);
if (!skipNewline) {
process.stdout.write("\n");
}
......@@ -140,24 +153,9 @@ class Builder {
* Build code-server within VS Code.
*/
private async build(vscodeSourcePath: string, vscodeVersion: string, codeServerVersion: string, finalBuildPath: string): Promise<void> {
const task = async <T>(message: string, fn: () => Promise<T>): Promise<T> => {
const time = Date.now();
this.log(`${message}...`, true);
try {
const t = await fn();
process.stdout.write(`took ${Date.now() - time}ms\n`);
return t;
} catch (error) {
process.stdout.write("failed\n");
throw error;
}
};
// Install dependencies (should be cached by CI).
// Ignore scripts since we'll install VS Code dependencies separately.
await task("Installing code-server dependencies", async () => {
await util.promisify(cp.exec)("yarn --ignore-scripts", { cwd: this.rootPath });
await util.promisify(cp.exec)("yarn postinstall", { cwd: this.rootPath });
await this.task("Installing code-server dependencies", async () => {
await util.promisify(cp.exec)("yarn", { cwd: this.rootPath });
});
// Download and prepare VS Code if necessary (should be cached by CI).
......@@ -165,18 +163,18 @@ class Builder {
if (exists) {
this.log("Using existing VS Code directory");
} else {
await task("Cloning VS Code", () => {
await this.task("Cloning VS Code", () => {
return util.promisify(cp.exec)(
"git clone https://github.com/microsoft/vscode"
+ ` --quiet --branch "${vscodeVersion}"`
+ ` --single-branch --depth=1 "${vscodeSourcePath}"`);
});
await task("Installing VS Code dependencies", () => {
await this.task("Installing VS Code dependencies", () => {
return util.promisify(cp.exec)("yarn", { cwd: vscodeSourcePath });
});
await task("Building default extensions", () => {
await this.task("Building default extensions", () => {
return util.promisify(cp.exec)(
"yarn gulp compile-extensions-build --max-old-space-size=32384",
{ cwd: vscodeSourcePath },
......@@ -185,14 +183,14 @@ class Builder {
}
// Clean before patching or it could fail if already patched.
await task("Patching VS Code", async () => {
await this.task("Patching VS Code", async () => {
await util.promisify(cp.exec)("git reset --hard", { cwd: vscodeSourcePath });
await util.promisify(cp.exec)("git clean -fd", { cwd: vscodeSourcePath });
await util.promisify(cp.exec)(`git apply ${this.rootPath}/scripts/vscode.patch`, { cwd: vscodeSourcePath });
});
const serverPath = path.join(vscodeSourcePath, "src/vs/server");
await task("Copying code-server into VS Code", async () => {
await this.task("Copying code-server into VS Code", async () => {
await fs.remove(serverPath);
await fs.mkdirp(serverPath);
await Promise.all(["main.js", "node_modules", "src", "typings"].map((fileName) => {
......@@ -200,16 +198,16 @@ class Builder {
}));
});
await task("Building VS Code", () => {
await this.task("Building VS Code", () => {
return util.promisify(cp.exec)("yarn gulp compile-build --max-old-space-size=32384", { cwd: vscodeSourcePath });
});
await task("Optimizing VS Code", async () => {
await this.task("Optimizing VS Code", async () => {
await fs.copyFile(path.join(this.rootPath, "scripts/optimize.js"), path.join(vscodeSourcePath, "coder.js"));
await util.promisify(cp.exec)(`yarn gulp optimize --max-old-space-size=32384 --gulpfile ./coder.js`, { cwd: vscodeSourcePath });
});
const { productJson, packageJson } = await task("Generating final package.json and product.json", async () => {
const { productJson, packageJson } = await this.task("Generating final package.json and product.json", async () => {
const merge = async (name: string, extraJson: { [key: string]: string } = {}): Promise<{ [key: string]: string }> => {
const [aJson, bJson] = (await Promise.all([
fs.readFile(path.join(vscodeSourcePath, `${name}.json`), "utf8"),
......@@ -247,13 +245,13 @@ class Builder {
});
if (process.env.MINIFY) {
await task("Minifying VS Code", () => {
await this.task("Minifying VS Code", () => {
return util.promisify(cp.exec)("yarn gulp minify --max-old-space-size=32384 --gulpfile ./coder.js", { cwd: vscodeSourcePath });
});
}
const finalServerPath = path.join(finalBuildPath, "out/vs/server");
await task("Copying into final build directory", async () => {
await this.task("Copying into final build directory", async () => {
await fs.remove(finalBuildPath);
await fs.mkdirp(finalBuildPath);
await Promise.all([
......@@ -271,7 +269,7 @@ class Builder {
});
if (process.env.MINIFY) {
await task("Restricting to production dependencies", async () => {
await this.task("Restricting to production dependencies", async () => {
await Promise.all(["package.json", "yarn.lock"].map((fileName) => {
Promise.all([
fs.copy(path.join(this.rootPath, fileName), path.join(finalServerPath, fileName)),
......@@ -279,10 +277,9 @@ class Builder {
]);
}));
await Promise.all([
util.promisify(cp.exec)("yarn --production --ignore-scripts", { cwd: finalServerPath }),
util.promisify(cp.exec)("yarn --production", { cwd: finalBuildPath }),
]);
await Promise.all([finalServerPath, finalBuildPath].map((cwd) => {
return util.promisify(cp.exec)("yarn --production", { cwd });
}));
await Promise.all(["package.json", "yarn.lock"].map((fileName) => {
return Promise.all([
......@@ -293,7 +290,7 @@ class Builder {
});
}
await task("Writing final package.json and product.json", () => {
await this.task("Writing final package.json and product.json", () => {
return Promise.all([
fs.writeFile(path.join(finalBuildPath, "package.json"), JSON.stringify(packageJson, null, 2)),
fs.writeFile(path.join(finalBuildPath, "product.json"), JSON.stringify(productJson, null, 2)),
......@@ -301,7 +298,7 @@ class Builder {
});
// This is so it doesn't get cached along with VS Code (no point).
await task("Removing copied server", () => fs.remove(serverPath));
await this.task("Removing copied server", () => fs.remove(serverPath));
// Prepend code to the target which enables finding files within the binary.
const prependLoader = async (relativeFilePath: string): Promise<void> => {
......@@ -322,7 +319,7 @@ class Builder {
await fs.writeFile(filePath, shim + (await fs.readFile(filePath, "utf8")));
};
await task("Prepending nbin loader", () => {
await this.task("Prepending nbin loader", () => {
return Promise.all([
prependLoader("out/vs/server/main.js"),
prependLoader("out/bootstrap-fork.js"),
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册