Simplify build and development steps
This commit is contained in:
parent
88cef85f62
commit
4cd2f2cd52
23
README.md
23
README.md
@ -58,17 +58,13 @@ arguments when launching code-server with Docker. See
|
|||||||
|
|
||||||
### Build
|
### Build
|
||||||
|
|
||||||
- If you also plan on developing, set the `OUT` environment variable. Otherwise
|
```shell
|
||||||
it will build in this directory which will cause issues because `yarn watch`
|
export OUT=/path/to/output/build # Optional if only building. Required if also developing.
|
||||||
will try to compile the build directory as well.
|
yarn build ${vscodeVersion} ${codeServerVersion} # See travis.yml for the VS Code version to use.
|
||||||
- Run `yarn build ${vscodeVersion} ${codeServerVersion}` in this directory (for
|
# The code-server version can be anything you want.
|
||||||
example: `yarn build 1.36.0 development`).
|
node ~/path/to/output/build/out/vs/server/main.js # You can run the built JavaScript with Node.
|
||||||
- If you target the same VS Code version our Travis builds do everything will
|
yarn binary ${vscodeVersion} ${codeServerVersion} # Or you can package it into a binary.
|
||||||
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.
|
|
||||||
|
|
||||||
## Known Issues
|
## Known Issues
|
||||||
|
|
||||||
@ -109,11 +105,12 @@ data collected to improve code-server.
|
|||||||
```shell
|
```shell
|
||||||
git clone https://github.com/microsoft/vscode
|
git clone https://github.com/microsoft/vscode
|
||||||
cd 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
|
git clone https://github.com/cdr/code-server src/vs/server
|
||||||
cd src/vs/server
|
cd src/vs/server
|
||||||
yarn patch:apply
|
|
||||||
yarn
|
yarn
|
||||||
|
yarn patch:apply
|
||||||
yarn watch
|
yarn watch
|
||||||
# Wait for the initial compilation to complete (it will say "Finished compilation").
|
# Wait for the initial compilation to complete (it will say "Finished compilation").
|
||||||
# Run the next command in another shell.
|
# Run the next command in another shell.
|
||||||
|
12
package.json
12
package.json
@ -2,15 +2,13 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"runner": "cd ./scripts && node --max-old-space-size=32384 -r ts-node/register ./build.ts",
|
"runner": "cd ./scripts && node --max-old-space-size=32384 -r ts-node/register ./build.ts",
|
||||||
"preinstall": "yarn runner ensure-in-vscode && cd ../../../ && yarn || true",
|
"start": "nodemon --watch ../../../out --verbose ../../../out/vs/server/main.js",
|
||||||
"postinstall": "rm -rf node_modules/@types/node",
|
"watch": "cd ../../../ && yarn watch",
|
||||||
"start": "yarn runner ensure-in-vscode && nodemon --watch ../../../out --verbose ../../../out/vs/server/main.js",
|
"build": "yarn && yarn runner build",
|
||||||
"watch": "yarn runner ensure-in-vscode && cd ../../../ && yarn watch",
|
|
||||||
"build": "yarn --ignore-scripts && yarn runner build",
|
|
||||||
"package": "yarn runner package",
|
"package": "yarn runner package",
|
||||||
"binary": "yarn runner binary",
|
"binary": "yarn runner binary",
|
||||||
"patch:generate": "yarn runner ensure-in-vscode && cd ../../../ && git diff --staged > ./src/vs/server/scripts/vscode.patch",
|
"patch:generate": "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:apply": "cd ../../../ && git apply ./src/vs/server/scripts/vscode.patch"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@coder/nbin": "^1.2.2",
|
"@coder/nbin": "^1.2.2",
|
||||||
|
@ -20,21 +20,34 @@ class Builder {
|
|||||||
private readonly rootPath = path.resolve(__dirname, "..");
|
private readonly rootPath = path.resolve(__dirname, "..");
|
||||||
private readonly outPath = process.env.OUT || this.rootPath;
|
private readonly outPath = process.env.OUT || this.rootPath;
|
||||||
private _target?: "darwin" | "alpine" | "linux";
|
private _target?: "darwin" | "alpine" | "linux";
|
||||||
private task?: Task;
|
private currentTask?: Task;
|
||||||
|
|
||||||
public run(task: Task | undefined, args: string[]): void {
|
public run(task: Task | undefined, args: string[]): void {
|
||||||
this.task = task;
|
this.currentTask = task;
|
||||||
this.doRun(task, args).catch((error) => {
|
this.doRun(task, args).catch((error) => {
|
||||||
console.error(error.message);
|
console.error(error.message);
|
||||||
process.exit(1);
|
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.
|
* Writes to stdout with an optional newline.
|
||||||
*/
|
*/
|
||||||
private log(message: string, skipNewline: boolean = false): void {
|
private log(message: string, skipNewline: boolean = false): void {
|
||||||
process.stdout.write(`[${this.task || "default"}] ${message}`);
|
process.stdout.write(`[${this.currentTask || "default"}] ${message}`);
|
||||||
if (!skipNewline) {
|
if (!skipNewline) {
|
||||||
process.stdout.write("\n");
|
process.stdout.write("\n");
|
||||||
}
|
}
|
||||||
@ -140,24 +153,9 @@ class Builder {
|
|||||||
* Build code-server within VS Code.
|
* Build code-server within VS Code.
|
||||||
*/
|
*/
|
||||||
private async build(vscodeSourcePath: string, vscodeVersion: string, codeServerVersion: string, finalBuildPath: string): Promise<void> {
|
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).
|
// Install dependencies (should be cached by CI).
|
||||||
// Ignore scripts since we'll install VS Code dependencies separately.
|
await this.task("Installing code-server dependencies", async () => {
|
||||||
await task("Installing code-server dependencies", async () => {
|
await util.promisify(cp.exec)("yarn", { cwd: this.rootPath });
|
||||||
await util.promisify(cp.exec)("yarn --ignore-scripts", { cwd: this.rootPath });
|
|
||||||
await util.promisify(cp.exec)("yarn postinstall", { cwd: this.rootPath });
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Download and prepare VS Code if necessary (should be cached by CI).
|
// Download and prepare VS Code if necessary (should be cached by CI).
|
||||||
@ -165,18 +163,18 @@ class Builder {
|
|||||||
if (exists) {
|
if (exists) {
|
||||||
this.log("Using existing VS Code directory");
|
this.log("Using existing VS Code directory");
|
||||||
} else {
|
} else {
|
||||||
await task("Cloning VS Code", () => {
|
await this.task("Cloning VS Code", () => {
|
||||||
return util.promisify(cp.exec)(
|
return util.promisify(cp.exec)(
|
||||||
"git clone https://github.com/microsoft/vscode"
|
"git clone https://github.com/microsoft/vscode"
|
||||||
+ ` --quiet --branch "${vscodeVersion}"`
|
+ ` --quiet --branch "${vscodeVersion}"`
|
||||||
+ ` --single-branch --depth=1 "${vscodeSourcePath}"`);
|
+ ` --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 });
|
return util.promisify(cp.exec)("yarn", { cwd: vscodeSourcePath });
|
||||||
});
|
});
|
||||||
|
|
||||||
await task("Building default extensions", () => {
|
await this.task("Building default extensions", () => {
|
||||||
return util.promisify(cp.exec)(
|
return util.promisify(cp.exec)(
|
||||||
"yarn gulp compile-extensions-build --max-old-space-size=32384",
|
"yarn gulp compile-extensions-build --max-old-space-size=32384",
|
||||||
{ cwd: vscodeSourcePath },
|
{ cwd: vscodeSourcePath },
|
||||||
@ -185,14 +183,14 @@ class Builder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Clean before patching or it could fail if already patched.
|
// 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 reset --hard", { cwd: vscodeSourcePath });
|
||||||
await util.promisify(cp.exec)("git clean -fd", { 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 });
|
await util.promisify(cp.exec)(`git apply ${this.rootPath}/scripts/vscode.patch`, { cwd: vscodeSourcePath });
|
||||||
});
|
});
|
||||||
|
|
||||||
const serverPath = path.join(vscodeSourcePath, "src/vs/server");
|
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.remove(serverPath);
|
||||||
await fs.mkdirp(serverPath);
|
await fs.mkdirp(serverPath);
|
||||||
await Promise.all(["main.js", "node_modules", "src", "typings"].map((fileName) => {
|
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 });
|
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 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 });
|
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 merge = async (name: string, extraJson: { [key: string]: string } = {}): Promise<{ [key: string]: string }> => {
|
||||||
const [aJson, bJson] = (await Promise.all([
|
const [aJson, bJson] = (await Promise.all([
|
||||||
fs.readFile(path.join(vscodeSourcePath, `${name}.json`), "utf8"),
|
fs.readFile(path.join(vscodeSourcePath, `${name}.json`), "utf8"),
|
||||||
@ -247,13 +245,13 @@ class Builder {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (process.env.MINIFY) {
|
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 });
|
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");
|
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.remove(finalBuildPath);
|
||||||
await fs.mkdirp(finalBuildPath);
|
await fs.mkdirp(finalBuildPath);
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
@ -271,7 +269,7 @@ class Builder {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (process.env.MINIFY) {
|
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) => {
|
await Promise.all(["package.json", "yarn.lock"].map((fileName) => {
|
||||||
Promise.all([
|
Promise.all([
|
||||||
fs.copy(path.join(this.rootPath, fileName), path.join(finalServerPath, fileName)),
|
fs.copy(path.join(this.rootPath, fileName), path.join(finalServerPath, fileName)),
|
||||||
@ -279,10 +277,9 @@ class Builder {
|
|||||||
]);
|
]);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([finalServerPath, finalBuildPath].map((cwd) => {
|
||||||
util.promisify(cp.exec)("yarn --production --ignore-scripts", { cwd: finalServerPath }),
|
return util.promisify(cp.exec)("yarn --production", { cwd });
|
||||||
util.promisify(cp.exec)("yarn --production", { cwd: finalBuildPath }),
|
}));
|
||||||
]);
|
|
||||||
|
|
||||||
await Promise.all(["package.json", "yarn.lock"].map((fileName) => {
|
await Promise.all(["package.json", "yarn.lock"].map((fileName) => {
|
||||||
return Promise.all([
|
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([
|
return Promise.all([
|
||||||
fs.writeFile(path.join(finalBuildPath, "package.json"), JSON.stringify(packageJson, null, 2)),
|
fs.writeFile(path.join(finalBuildPath, "package.json"), JSON.stringify(packageJson, null, 2)),
|
||||||
fs.writeFile(path.join(finalBuildPath, "product.json"), JSON.stringify(productJson, 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).
|
// 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.
|
// Prepend code to the target which enables finding files within the binary.
|
||||||
const prependLoader = async (relativeFilePath: string): Promise<void> => {
|
const prependLoader = async (relativeFilePath: string): Promise<void> => {
|
||||||
@ -322,7 +319,7 @@ class Builder {
|
|||||||
await fs.writeFile(filePath, shim + (await fs.readFile(filePath, "utf8")));
|
await fs.writeFile(filePath, shim + (await fs.readFile(filePath, "utf8")));
|
||||||
};
|
};
|
||||||
|
|
||||||
await task("Prepending nbin loader", () => {
|
await this.task("Prepending nbin loader", () => {
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
prependLoader("out/vs/server/main.js"),
|
prependLoader("out/vs/server/main.js"),
|
||||||
prependLoader("out/bootstrap-fork.js"),
|
prependLoader("out/bootstrap-fork.js"),
|
||||||
|
Reference in New Issue
Block a user