Compare commits

...

25 Commits

Author SHA1 Message Date
Anmol Sethi
17267bd801 Add Dockerfile and some cleanup (#57) 2019-03-06 18:59:43 -08:00
Michael Desantis
ac56fcaafc Remove unused markup from password page (#49) 2019-03-06 18:47:05 -08:00
Michael Desantis
e20b79b5cc Generate secure passwords, fixes issue #26 (#51) 2019-03-06 16:25:44 -08:00
Philipp Gillé
e99f8abc3c Fix spelling error (#46) 2019-03-06 16:21:33 -08:00
Asher
994531d8bb Add task for packaging release (#6)
* Add task for packaging release

* Modify package task to package a single binary

This is so it can be used as part of the build/release script.

* Package release as part of Travis deploy

* Set platform env var

* Add arch env var

* Make version available to the code

* Use tar for Linux and zip for Mac & Windows
2019-03-06 18:15:52 -06:00
Kyle Carberry
8916cb9bb2 Update to vscode 1.31.1 (#45) 2019-03-06 11:10:23 -08:00
Ammar Bandukwala
d4867ca430 Cleanup English in README (#21) 2019-03-06 10:11:27 -08:00
Icebob
3fbdb2e46c Implement #4 - fix password via CLI (#5) 2019-03-06 00:08:43 -08:00
Ammar Bandukwala
1d8da2161f Add value props to readme (#20) 2019-03-05 17:45:21 -08:00
Kyle Carberry
414eb7076f Update element fill to replace file URIs in image tags 2019-03-06 00:06:44 +00:00
Asher
2b3d2933eb Updated binary name in issue templates 2019-03-05 17:23:13 -06:00
Andrew Grekov
14ead1a62f Fixes calculating number of threads for HappyPack (#10) 2019-03-05 15:02:49 -08:00
John McCambridge
3b48c57861 Fix port number in docs (#12) 2019-03-05 13:53:35 -08:00
Colin
c772e920cd Add Discord widget to README (#16) 2019-03-05 13:53:05 -08:00
Ammar Bandukwala
e6aa74c412 Merge pull request #7 from codercom/fix-doc
Clarify that cloud offering is seperate from the open source
2019-03-05 10:52:43 -08:00
Ammar Bandukwala
838c8a6f2c Clarify that the cloud offering is seperate from the open source 2019-03-05 12:51:34 -06:00
Kyle Carberry
4028e33529 Update travis.yml with new credentials 2019-03-05 05:20:57 +00:00
Kyle Carberry
ec94a92a5f Merge branch 'master' of github.com:codercom/code-server 2019-03-05 04:54:53 +00:00
Kyle Carberry
379a5243fe Update api key secret 2019-03-05 04:54:37 +00:00
Asher
47765dde23 Add ping/pong to the protocol (#2) 2019-03-04 19:26:17 -08:00
Kyle Carberry
d48d72cb79 Filter out secrets in CI 2019-03-05 01:20:25 +00:00
Kyle Carberry
31518e9754 Make ripgrep executable on extract 2019-03-05 00:42:02 +00:00
Kyle Carberry
1e0d330778 Directly point to the logger src 2019-03-05 00:29:19 +00:00
Kyle Carberry
ef6369d62f Add prerelease 2019-03-05 00:21:29 +00:00
Asher
5b0d11e470 Use localhost for code-server domain 2019-03-04 16:11:48 -06:00
28 changed files with 620 additions and 96 deletions

1
.dockerignore Normal file
View File

@@ -0,0 +1 @@
Dockerfile

View File

@@ -9,7 +9,7 @@ assignees: ''
<!-- Please search existing issues to avoid creating duplicates. --> <!-- Please search existing issues to avoid creating duplicates. -->
<!-- All extension-specific issues should be created with the `Extension Bug` template. --> <!-- All extension-specific issues should be created with the `Extension Bug` template. -->
- `vscode-remote` version: <!-- The version of vscode-remote --> - `code-server` version: <!-- The version of code-server -->
- OS Version: <!-- OS version, cloud provider, --> - OS Version: <!-- OS version, cloud provider, -->
#### Steps to Reproduce #### Steps to Reproduce

View File

@@ -8,7 +8,7 @@ assignees: ''
<!-- Please search existing issues to avoid creating duplicates. --> <!-- Please search existing issues to avoid creating duplicates. -->
- `vscode-remote` version: <!-- The version of vscode-remote --> - `code-server` version: <!-- The version of code-server -->
- OS Version: <!-- OS version, cloud provider, --> - OS Version: <!-- OS version, cloud provider, -->
- Extension: <!-- Link to extension --> - Extension: <!-- Link to extension -->

1
.gitignore vendored
View File

@@ -3,3 +3,4 @@ node_modules
dist dist
out out
.DS_Store .DS_Store
release

View File

@@ -1,33 +1,37 @@
language: node_js language: node_js
node_js: node_js:
- 8.9.3 - 8.9.3
filter_secrets: false env:
- VERSION="1.31.1-$TRAVIS_BUILD_NUMBER"
matrix: matrix:
include: include:
- os: linux - os: linux
dist: ubuntu dist: ubuntu
- os: osx - os: osx
before_install: before_install:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install libxkbfile-dev libsecret-1-dev; - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install libxkbfile-dev
fi libsecret-1-dev; fi
script: script:
- scripts/build.sh - scripts/build.sh
# before_deploy: before_deploy:
# - export TRAVIS_TAG="1.0.$TRAVIS_BUILD_NUMBER" - echo "$VERSION" "$TRAVIS_COMMIT"
# - echo "$TRAVIS_TAG" "$TRAVIS_COMMIT" - git config --local user.name "$USER_NAME"
# - git config --local user.name "$USER_NAME" - git config --local user.email "$USER_EMAIL"
# - git config --local user.email "$USER_EMAIL" - git tag "$VERSION" "$TRAVIS_COMMIT"
# - git tag "$TRAVIS_TAG" "$TRAVIS_COMMIT" - yarn task package "$VERSION"
# deploy: deploy:
# provider: releases provider: releases
# tag_name: $TRAVIS_TAG file_glob: true
# target_commitish: $TRAVIS_COMMIT draft: true
# name: $TRAVIS_TAG tag_name: "$VERSION"
# skip_cleanup: true target_commitish: "$TRAVIS_COMMIT"
# api_key: name: "$VERSION"
# secure: T/yqCIeqLifteriv8D3CnehNFzSBP309GZqeUfyx8Q+xSQEttA9Enxl+Qw9GkdedYTN4J56iucHIac6CwcvKSKIXqk80CeSEW0BNxZs5wIgv4rRMMy/GAX0NBWKNOkoGlH8M6VyQcM7eY2iGAn1EX755PHalk6rWwfsauRANOQyb2DXQBan5C0YUnogq2qcW1xkIwlXH7l0Ekbtego0f6QPv0rSyOcL1LKm6xk0Aq+xLNKJkT6TSL6xYpkPlZLjnql09Nspkqs6NehWlft2n09bHqAtjNnWw9OYCvxp8mdHeTE5uShuEqYPzdYU5LVFoE7wElI8uqS66noaA18ytZYGw2IrY6GZcn+wtR6WyM2+YXl2HclL1/Fs6Vn8+zwq2IBZchBNv3KJSn1dxiqLlD/s6YQyni17x/9FhtFoNUvsbY5zSC1xrnNQBQWFg0TRnoC9rPR+7hQtT1+5+CvRxpvcNWnPuA22919PFE79ejJulPmsnyF+YLs9c6APJgOpOO1f6fKt5Mcb02dubPqGcQ9NbqUUNTl4IUvEtjG0LnFAgEGerxAcsdnUTxzBVf0LJLlhRKW1BigUTbRwfUJL1DN0mWg9cg7fL5VqrogvNq3uRguxOsYr+bcHDbimQSAY3No3fAkTTqQSJh56Dx57/Un18KxuOTiRB9de1RtiudsI= skip_cleanup: true
# file_glob: true api_key:
# file: packages/server/cli-* secure: YL/x24KjYjgYXPcJWk3FV7FGxI79Mh6gBECQEcdlf3fkLEoKFVgzHBoUNWrFPzyR4tgLyWNAgcpD9Lkme1TRWTom7UPjXcwMNyLcLa+uec7ciSAnYD9ntLTpiCuPDD1u0LtRGclSi/EHQ+F8YVq+HZJpXTsJeAmOmihma3GVbGKSZr+BRum+0YZSG4w+o4TOlYzw/4bLWS52MogZcwpjd+hemBbgXLuGU2ziKv2vEKCZFbEeA16II4x1WLI4mutDdCeh7+3aLzGLwDa49NxtsVYNjyNFF75JhCTCNA55e2YMiLz9Uq69IXe/mi5F7xUaFfhIqqLNyKBnKeEOzu3dYnc+8n3LjnQ+00PmkF05nx9kBn3UfV1kwQGh6QbyDmTtBP07rtUMyI14aeQqHjxsaVRdMnwj9Q2DjXRr8UDqESZF0rmK3pHCXS2fBhIzLE8tLVW5Heiba2pQRFMHMZW+KBE97FzcFh7is90Ait3T8enfcd/PWFPYoBejDAdjwxwOkezh5N5ZkYquEfDYuWrFi6zRFCktsruaAcA+xGtTf9oilBBzUqu8Ie+YFWH5me83xakcblJWdaW/D2rLJAJH3m6LFm8lBqyUgDX5t/etob6CpDuYHu5D1J3XINOj/+aLAcadq6qlh70PMZS3zYffUu3JlzaD2amlSHIT8b5YXFc=
# on: file:
# repo: codercom/code-server - release/*.tar.gz
# branch: master - release/*.zip
on:
repo: codercom/code-server
branch: master

26
Dockerfile Normal file
View File

@@ -0,0 +1,26 @@
FROM node:8.15.0
# Install VS Code's deps. These are the only two it seems we need.
RUN apt-get update
RUN apt-get install -y libxkbfile-dev libsecret-1-dev
# Ensure latest yarn.
RUN npm install -g yarn
# In the future, we can use https://github.com/yarnpkg/rfcs/pull/53 to make it use the node_modules
# directly which should be faster.
WORKDIR /src
COPY . .
RUN yarn
RUN yarn task build:server:binary
# We deploy with ubuntu so that devs have a familiar environemnt.
FROM ubuntu:18.10
RUN apt-get update
RUN apt-get install -y openssl
RUN apt-get install -y net-tools
WORKDIR /root/project
COPY --from=0 /src/packages/server/cli-linux /usr/local/bin/code-server
EXPOSE 8443
# Unfortunately `.` does not work with code-server.
CMD code-server $PWD

View File

@@ -3,15 +3,36 @@
[!["Open Issues"](https://img.shields.io/github/issues-raw/codercom/code-server.svg)](https://github.com/codercom/code-server/issues) [!["Open Issues"](https://img.shields.io/github/issues-raw/codercom/code-server.svg)](https://github.com/codercom/code-server/issues)
[!["Latest Release"](https://img.shields.io/github/release/codercom/code-server.svg)](https://github.com/codercom/code-server/releases/latest) [!["Latest Release"](https://img.shields.io/github/release/codercom/code-server.svg)](https://github.com/codercom/code-server/releases/latest)
[![MIT license](https://img.shields.io/badge/license-MIT-green.svg)](#) [![MIT license](https://img.shields.io/badge/license-MIT-green.svg)](#)
[![Discord](https://discordapp.com/api/guilds/463752820026376202/widget.png)](https://discord.gg/zxSwN8Z)
`code-server` is VS Code running on a remote server, accessible through the browser. `code-server` is [VS Code](https://github.com/Microsoft/vscode) running on a remote server, accessible through the browser.
Try it out:
```bash
docker run -p localhost:8443:8443 -v "${PWD}:/root/project" codercom/code-server code-server --allow-http --no-auth
```
- Code on your Chromebook, tablet, and laptop with a consistent dev environment.
- If you have a Windows or Mac workstation, more easily develop for Linux.
- Take advantage of large cloud servers to speed up tests, compilations, downloads, and more.
- Preserve battery life when you're on the go.
- All intensive computation is ran on your server.
- You're no longer running excess instances of Chrome.
![Screenshot](/doc/assets/ide.png) ![Screenshot](/doc/assets/ide.png)
## Getting Started ## Getting Started
### Hosted
[Try `code-server` now](https://coder.com/signup) for free at coder.com. [Try `code-server` now](https://coder.com/signup) for free at coder.com.
### Docker
See docker oneliner mentioned above. Dockerfile is at [/Dockerfile](/Dockerfile).
### Binaries
1. [Download a binary](https://github.com/codercom/code-server/releases) (Linux and OSX supported. Windows coming soon) 1. [Download a binary](https://github.com/codercom/code-server/releases) (Linux and OSX supported. Windows coming soon)
2. Start the binary with the project directory as the first argument 2. Start the binary with the project directory as the first argument
@@ -19,7 +40,7 @@
code-server <inital directory to open> code-server <inital directory to open>
``` ```
> You will be prompted to enter the password shown in the CLI > You will be prompted to enter the password shown in the CLI
`code-server` should now be running at https://<IP>:8443. `code-server` should now be running at https://localhost:8443.
> code-server uses a self-signed SSL certificate that may prompt your browser to ask you some additional questions before you proceed. Please [read here](doc/self-hosted/index.md) for more information. > code-server uses a self-signed SSL certificate that may prompt your browser to ask you some additional questions before you proceed. Please [read here](doc/self-hosted/index.md) for more information.
@@ -43,7 +64,7 @@ How to [secure your setup](/doc/security/ssl.md).
## Contributing ## Contributing
Guides on setup for development will be coming soon. :) Development guides are coming soon.
## License ## License
@@ -51,7 +72,7 @@ Guides on setup for development will be coming soon. :)
## Enterprise ## Enterprise
Visit [our enterprise page](https://coder.com/enterprise) for more information on our enterprise offering. Visit [our enterprise page](https://coder.com/enterprise) for more information about our enterprise offering.
## Commercialization ## Commercialization

View File

@@ -224,7 +224,7 @@ const ensureCloned = register("vscode:clone", async (runner) => {
} }
runner.cwd = vscodePath; runner.cwd = vscodePath;
const checkout = await runner.execute("git", ["checkout", "tags/1.31.0"]); const checkout = await runner.execute("git", ["checkout", "tags/1.31.1"]);
if (checkout.exitCode !== 0) { if (checkout.exitCode !== 0) {
throw new Error(`Failed to checkout: ${checkout.stderr}`); throw new Error(`Failed to checkout: ${checkout.stderr}`);
} }
@@ -260,4 +260,30 @@ const ensurePatched = register("vscode:patch", async (runner) => {
} }
}); });
register("package", async (runner, releaseTag) => {
if (!releaseTag) {
throw new Error("Please specify the release tag.");
}
const releasePath = path.resolve(__dirname, "../release");
const archiveName = `code-server-${releaseTag}-${os.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 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;
await os.platform() === "linux"
? runner.execute("tar", ["-cvzf", `${archiveName}.tar.gz`, `${archiveName}`])
: runner.execute("zip", ["-r", `${archiveName}.zip`, `${archiveName}`]);
});
run(); run();

View File

@@ -8,7 +8,7 @@
This document pertains to Coder specific implementations of VS Code. For documentation on how to use VS Code itself, please refer to the official [documentation for VS Code](https://code.visualstudio.com/docs) This document pertains to Coder specific implementations of VS Code. For documentation on how to use VS Code itself, please refer to the official [documentation for VS Code](https://code.visualstudio.com/docs)
It takes just a few minutes to get your own self-hosted server running. If you've got a machine running macOS, Windows, or Linux, you're ready to start the binary which listens on port `8080` by default. It takes just a few minutes to get your own self-hosted server running. If you've got a machine running macOS, Windows, or Linux, you're ready to start the binary which listens on port `8443` by default.
<!-- <!--
DO NOT CHANGE THIS TO A CODEBLOCK. DO NOT CHANGE THIS TO A CODEBLOCK.
@@ -20,7 +20,7 @@ It takes just a few minutes to get your own self-hosted server running. If you'v
1. Visit [the releases](https://github.com/codercom/code-server/releases) page and download the latest cli for your operating system 1. Visit [the releases](https://github.com/codercom/code-server/releases) page and download the latest cli for your operating system
2. Double click the executable to run in the current directory 2. Double click the executable to run in the current directory
3. Copy the password that appears in the cli<img src="../assets/cli.png"> 3. Copy the password that appears in the cli<img src="../assets/cli.png">
4. In your browser navigate to `localhost:8080` 4. In your browser navigate to `localhost:8443`
5. Paste the password from the cli into the login window<img src="../assets/server-password-modal.png"> 5. Paste the password from the cli into the login window<img src="../assets/server-password-modal.png">
> NOTE: Be careful with your password as sharing it will grant those users access to your server's file system > NOTE: Be careful with your password as sharing it will grant those users access to your server's file system
@@ -44,10 +44,11 @@ OPTIONS
-d, --data-dir=data-dir -d, --data-dir=data-dir
-h, --host=host [default: 0.0.0.0] -h, --host=host [default: 0.0.0.0]
-o, --open Open in browser on startup -o, --open Open in browser on startup
-p, --port=port [default: 8080] Port to bind on -p, --port=port [default: 8443] Port to bind on
-v, --version show CLI version -v, --version show CLI version
--cert=cert --cert=cert
--cert-key=cert-key --cert-key=cert-key
--password=password
--help show CLI help --help show CLI help
``` ```
@@ -55,14 +56,14 @@ OPTIONS
Use `code-server -d (path/to/directory)` or `code-server --data-dir=(path/to/directory)`, excluding the parentheses to specify the root folder that VS Code will start in Use `code-server -d (path/to/directory)` or `code-server --data-dir=(path/to/directory)`, excluding the parentheses to specify the root folder that VS Code will start in
### Host ### Host
By default, code-server will use `0.0.0.0` as it's address. This can be changed by using `code-server -h` or `code-server --host=` followed by the address you want to use. By default, code-server will use `0.0.0.0` as its address. This can be changed by using `code-server -h` or `code-server --host=` followed by the address you want to use.
> Example: `code-server -h 127.0.0.1` > Example: `code-server -h 127.0.0.1`
### Open ### Open
You can have the server automatically open the VS Code in your browser on startup by using the `code server -o` or `code-server --open` flags You can have the server automatically open the VS Code in your browser on startup by using the `code server -o` or `code-server --open` flags
### Port ### Port
By default, code-server will use `8080` as it's port. This can be changed by using `code-server -p` or `code-server --port=` followed by the port you want to use. By default, code-server will use `8443` as its port. This can be changed by using `code-server -p` or `code-server --port=` followed by the port you want to use.
> Example: `code-server -p 9000` > Example: `code-server -p 9000`
### Cert and Cert Key ### Cert and Cert Key

View File

@@ -19,21 +19,6 @@
<label class="mdc-floating-label" for="password">Password</label> <label class="mdc-floating-label" for="password">Password</label>
<div class="mdc-line-ripple"></div> <div class="mdc-line-ripple"></div>
</div> </div>
<div class="mdc-text-field-helper-line">
<div class="mdc-text-field-helper-text">helper text</div>
</div>
<div class="mdc-form-field">
<div class="mdc-checkbox">
<input type="checkbox" class="mdc-checkbox__native-control" id="remember" />
<div class="mdc-checkbox__background">
<svg class="mdc-checkbox__checkmark" viewBox="0 0 24 24">
<path class="mdc-checkbox__checkmark-path" fill="none" d="M1.73,12.91 8.1,19.28 22.79,4.59" />
</svg>
<div class="mdc-checkbox__mixedmark"></div>
</div>
</div>
<label for="remember">Remember Me</label>
</div>
<button id="submit" class="mdc-button mdc-button--unelevated"> <button id="submit" class="mdc-button mdc-button--unelevated">
<span class="mdc-button__label">Enter IDE</span> <span class="mdc-button__label">Enter IDE</span>
</button> </button>

View File

@@ -25,18 +25,37 @@ const newCreateElement = <K extends keyof HTMLElementTagNameMap>(tagName: K): HT
// tslint:disable-next-line:no-any // tslint:disable-next-line:no-any
return oldCreateElement.call(document, tagName as any); return oldCreateElement.call(document, tagName as any);
}; };
// tslint:disable-next-line:no-any
const getPropertyDescriptor = (object: any, id: string): PropertyDescriptor | undefined => {
let op = Object.getPrototypeOf(object);
while (!Object.getOwnPropertyDescriptor(op, id)) {
op = Object.getPrototypeOf(op);
}
return Object.getOwnPropertyDescriptor(op, id);
};
if (tagName === "img") {
const img = createElement("img");
const oldSrc = getPropertyDescriptor(img, "src");
if (!oldSrc) {
throw new Error("Failed to find src property");
}
Object.defineProperty(img, "src", {
get: (): string => {
return oldSrc!.get!.call(img);
},
set: (value: string): void => {
value = value.replace(/file:\/\//g, "/resource");
oldSrc!.set!.call(img, value);
},
});
return img;
}
if (tagName === "style") { if (tagName === "style") {
const style = createElement("style"); const style = createElement("style");
// tslint:disable-next-line:no-any
const getPropertyDescriptor = (object: any, id: string): PropertyDescriptor | undefined => {
let op = Object.getPrototypeOf(object);
while (!Object.getOwnPropertyDescriptor(op, id)) {
op = Object.getPrototypeOf(op);
}
return Object.getOwnPropertyDescriptor(op, id);
};
const oldInnerHtml = getPropertyDescriptor(style, "innerHTML"); const oldInnerHtml = getPropertyDescriptor(style, "innerHTML");
if (!oldInnerHtml) { if (!oldInnerHtml) {
throw new Error("Failed to find innerHTML property"); throw new Error("Failed to find innerHTML property");

View File

@@ -1,7 +1,7 @@
import { EventEmitter } from "events"; import { EventEmitter } from "events";
import { Emitter } from "@coder/events"; import { Emitter } from "@coder/events";
import { logger, field } from "@coder/logger"; import { logger, field } from "@coder/logger";
import { NewEvalMessage, ServerMessage, EvalDoneMessage, EvalFailedMessage, ClientMessage, WorkingInitMessage, EvalEventMessage } from "../proto"; import { Ping, NewEvalMessage, ServerMessage, EvalDoneMessage, EvalFailedMessage, ClientMessage, WorkingInitMessage, EvalEventMessage } from "../proto";
import { ReadWriteConnection, InitData, OperatingSystem, SharedProcessData } from "../common/connection"; import { ReadWriteConnection, InitData, OperatingSystem, SharedProcessData } from "../common/connection";
import { ActiveEvalHelper, EvalHelper, Disposer, ServerActiveEvalHelper } from "../common/helpers"; import { ActiveEvalHelper, EvalHelper, Disposer, ServerActiveEvalHelper } from "../common/helpers";
import { stringify, parse } from "../common/util"; import { stringify, parse } from "../common/util";
@@ -22,6 +22,11 @@ export class Client {
private readonly sharedProcessActiveEmitter = new Emitter<SharedProcessData>(); private readonly sharedProcessActiveEmitter = new Emitter<SharedProcessData>();
public readonly onSharedProcessActive = this.sharedProcessActiveEmitter.event; public readonly onSharedProcessActive = this.sharedProcessActiveEmitter.event;
// The socket timeout is 60s, so we need to send a ping periodically to
// prevent it from closing.
private pingTimeout: NodeJS.Timer | number | undefined;
private readonly pingTimeoutDelay = 30000;
/** /**
* @param connection Established connection to the server * @param connection Established connection to the server
*/ */
@@ -43,9 +48,16 @@ export class Client {
} }
}); });
connection.onClose(() => {
clearTimeout(this.pingTimeout as any); // tslint:disable-line no-any
this.pingTimeout = undefined;
});
this.initDataPromise = new Promise((resolve): void => { this.initDataPromise = new Promise((resolve): void => {
this.initDataEmitter.event(resolve); this.initDataEmitter.event(resolve);
}); });
this.startPinging();
} }
public dispose(): void { public dispose(): void {
@@ -214,6 +226,28 @@ export class Client {
socketPath: sharedProcessActiveMessage.getSocketPath(), socketPath: sharedProcessActiveMessage.getSocketPath(),
logPath: sharedProcessActiveMessage.getLogPath(), logPath: sharedProcessActiveMessage.getLogPath(),
}); });
} else if (message.hasPong()) {
// Nothing to do since we run the pings on a timer, in case either message
// is dropped which would break the ping cycle.
} else {
throw new Error("unknown message type");
} }
} }
private startPinging = (): void => {
if (typeof this.pingTimeout !== "undefined") {
return;
}
const schedulePing = (): void => {
this.pingTimeout = setTimeout(() => {
const clientMsg = new ClientMessage();
clientMsg.setPing(new Ping());
this.connection.send(clientMsg.serializeBinary());
schedulePing();
}, this.pingTimeoutDelay);
};
schedulePing();
}
} }

View File

@@ -3,7 +3,7 @@ import * as path from "path";
import { mkdir } from "fs"; import { mkdir } from "fs";
import { promisify } from "util"; import { promisify } from "util";
import { logger, field } from "@coder/logger"; import { logger, field } from "@coder/logger";
import { ClientMessage, WorkingInitMessage, ServerMessage } from "../proto"; import { Pong, ClientMessage, WorkingInitMessage, ServerMessage } from "../proto";
import { evaluate, ActiveEvaluation } from "./evaluate"; import { evaluate, ActiveEvaluation } from "./evaluate";
import { ForkProvider } from "../common/helpers"; import { ForkProvider } from "../common/helpers";
import { ReadWriteConnection } from "../common/connection"; import { ReadWriteConnection } from "../common/connection";
@@ -116,6 +116,11 @@ export class Server {
return; return;
} }
e.onEvent(evalEventMessage); e.onEvent(evalEventMessage);
} else if (message.hasPing()) {
logger.trace("ping");
const srvMsg = new ServerMessage();
srvMsg.setPong(new Pong());
this.connection.send(srvMsg.serializeBinary());
} else { } else {
throw new Error("unknown message type"); throw new Error("unknown message type");
} }

View File

@@ -7,6 +7,8 @@ message ClientMessage {
// node.proto // node.proto
NewEvalMessage new_eval = 11; NewEvalMessage new_eval = 11;
EvalEventMessage eval_event = 12; EvalEventMessage eval_event = 12;
Ping ping = 13;
} }
} }
@@ -21,6 +23,8 @@ message ServerMessage {
// vscode.proto // vscode.proto
SharedProcessActiveMessage shared_process_active = 17; SharedProcessActiveMessage shared_process_active = 17;
Pong pong = 18;
} }
} }

View File

@@ -16,6 +16,11 @@ export class ClientMessage extends jspb.Message {
getEvalEvent(): node_pb.EvalEventMessage | undefined; getEvalEvent(): node_pb.EvalEventMessage | undefined;
setEvalEvent(value?: node_pb.EvalEventMessage): void; setEvalEvent(value?: node_pb.EvalEventMessage): void;
hasPing(): boolean;
clearPing(): void;
getPing(): node_pb.Ping | undefined;
setPing(value?: node_pb.Ping): void;
getMsgCase(): ClientMessage.MsgCase; getMsgCase(): ClientMessage.MsgCase;
serializeBinary(): Uint8Array; serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): ClientMessage.AsObject; toObject(includeInstance?: boolean): ClientMessage.AsObject;
@@ -31,12 +36,14 @@ export namespace ClientMessage {
export type AsObject = { export type AsObject = {
newEval?: node_pb.NewEvalMessage.AsObject, newEval?: node_pb.NewEvalMessage.AsObject,
evalEvent?: node_pb.EvalEventMessage.AsObject, evalEvent?: node_pb.EvalEventMessage.AsObject,
ping?: node_pb.Ping.AsObject,
} }
export enum MsgCase { export enum MsgCase {
MSG_NOT_SET = 0, MSG_NOT_SET = 0,
NEW_EVAL = 11, NEW_EVAL = 11,
EVAL_EVENT = 12, EVAL_EVENT = 12,
PING = 13,
} }
} }
@@ -66,6 +73,11 @@ export class ServerMessage extends jspb.Message {
getSharedProcessActive(): vscode_pb.SharedProcessActiveMessage | undefined; getSharedProcessActive(): vscode_pb.SharedProcessActiveMessage | undefined;
setSharedProcessActive(value?: vscode_pb.SharedProcessActiveMessage): void; setSharedProcessActive(value?: vscode_pb.SharedProcessActiveMessage): void;
hasPong(): boolean;
clearPong(): void;
getPong(): node_pb.Pong | undefined;
setPong(value?: node_pb.Pong): void;
getMsgCase(): ServerMessage.MsgCase; getMsgCase(): ServerMessage.MsgCase;
serializeBinary(): Uint8Array; serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): ServerMessage.AsObject; toObject(includeInstance?: boolean): ServerMessage.AsObject;
@@ -84,6 +96,7 @@ export namespace ServerMessage {
evalEvent?: node_pb.EvalEventMessage.AsObject, evalEvent?: node_pb.EvalEventMessage.AsObject,
init?: WorkingInitMessage.AsObject, init?: WorkingInitMessage.AsObject,
sharedProcessActive?: vscode_pb.SharedProcessActiveMessage.AsObject, sharedProcessActive?: vscode_pb.SharedProcessActiveMessage.AsObject,
pong?: node_pb.Pong.AsObject,
} }
export enum MsgCase { export enum MsgCase {
@@ -93,6 +106,7 @@ export namespace ServerMessage {
EVAL_EVENT = 15, EVAL_EVENT = 15,
INIT = 16, INIT = 16,
SHARED_PROCESS_ACTIVE = 17, SHARED_PROCESS_ACTIVE = 17,
PONG = 18,
} }
} }

View File

@@ -43,7 +43,7 @@ if (goog.DEBUG && !COMPILED) {
* @private {!Array<!Array<number>>} * @private {!Array<!Array<number>>}
* @const * @const
*/ */
proto.ClientMessage.oneofGroups_ = [[11,12]]; proto.ClientMessage.oneofGroups_ = [[11,12,13]];
/** /**
* @enum {number} * @enum {number}
@@ -51,7 +51,8 @@ proto.ClientMessage.oneofGroups_ = [[11,12]];
proto.ClientMessage.MsgCase = { proto.ClientMessage.MsgCase = {
MSG_NOT_SET: 0, MSG_NOT_SET: 0,
NEW_EVAL: 11, NEW_EVAL: 11,
EVAL_EVENT: 12 EVAL_EVENT: 12,
PING: 13
}; };
/** /**
@@ -91,7 +92,8 @@ proto.ClientMessage.prototype.toObject = function(opt_includeInstance) {
proto.ClientMessage.toObject = function(includeInstance, msg) { proto.ClientMessage.toObject = function(includeInstance, msg) {
var f, obj = { var f, obj = {
newEval: (f = msg.getNewEval()) && node_pb.NewEvalMessage.toObject(includeInstance, f), newEval: (f = msg.getNewEval()) && node_pb.NewEvalMessage.toObject(includeInstance, f),
evalEvent: (f = msg.getEvalEvent()) && node_pb.EvalEventMessage.toObject(includeInstance, f) evalEvent: (f = msg.getEvalEvent()) && node_pb.EvalEventMessage.toObject(includeInstance, f),
ping: (f = msg.getPing()) && node_pb.Ping.toObject(includeInstance, f)
}; };
if (includeInstance) { if (includeInstance) {
@@ -138,6 +140,11 @@ proto.ClientMessage.deserializeBinaryFromReader = function(msg, reader) {
reader.readMessage(value,node_pb.EvalEventMessage.deserializeBinaryFromReader); reader.readMessage(value,node_pb.EvalEventMessage.deserializeBinaryFromReader);
msg.setEvalEvent(value); msg.setEvalEvent(value);
break; break;
case 13:
var value = new node_pb.Ping;
reader.readMessage(value,node_pb.Ping.deserializeBinaryFromReader);
msg.setPing(value);
break;
default: default:
reader.skipField(); reader.skipField();
break; break;
@@ -183,6 +190,14 @@ proto.ClientMessage.serializeBinaryToWriter = function(message, writer) {
node_pb.EvalEventMessage.serializeBinaryToWriter node_pb.EvalEventMessage.serializeBinaryToWriter
); );
} }
f = message.getPing();
if (f != null) {
writer.writeMessage(
13,
f,
node_pb.Ping.serializeBinaryToWriter
);
}
}; };
@@ -246,6 +261,36 @@ proto.ClientMessage.prototype.hasEvalEvent = function() {
}; };
/**
* optional Ping ping = 13;
* @return {?proto.Ping}
*/
proto.ClientMessage.prototype.getPing = function() {
return /** @type{?proto.Ping} */ (
jspb.Message.getWrapperField(this, node_pb.Ping, 13));
};
/** @param {?proto.Ping|undefined} value */
proto.ClientMessage.prototype.setPing = function(value) {
jspb.Message.setOneofWrapperField(this, 13, proto.ClientMessage.oneofGroups_[0], value);
};
proto.ClientMessage.prototype.clearPing = function() {
this.setPing(undefined);
};
/**
* Returns whether this field is set.
* @return {!boolean}
*/
proto.ClientMessage.prototype.hasPing = function() {
return jspb.Message.getField(this, 13) != null;
};
/** /**
* Generated by JsPbCodeGenerator. * Generated by JsPbCodeGenerator.
@@ -272,7 +317,7 @@ if (goog.DEBUG && !COMPILED) {
* @private {!Array<!Array<number>>} * @private {!Array<!Array<number>>}
* @const * @const
*/ */
proto.ServerMessage.oneofGroups_ = [[13,14,15,16,17]]; proto.ServerMessage.oneofGroups_ = [[13,14,15,16,17,18]];
/** /**
* @enum {number} * @enum {number}
@@ -283,7 +328,8 @@ proto.ServerMessage.MsgCase = {
EVAL_DONE: 14, EVAL_DONE: 14,
EVAL_EVENT: 15, EVAL_EVENT: 15,
INIT: 16, INIT: 16,
SHARED_PROCESS_ACTIVE: 17 SHARED_PROCESS_ACTIVE: 17,
PONG: 18
}; };
/** /**
@@ -326,7 +372,8 @@ proto.ServerMessage.toObject = function(includeInstance, msg) {
evalDone: (f = msg.getEvalDone()) && node_pb.EvalDoneMessage.toObject(includeInstance, f), evalDone: (f = msg.getEvalDone()) && node_pb.EvalDoneMessage.toObject(includeInstance, f),
evalEvent: (f = msg.getEvalEvent()) && node_pb.EvalEventMessage.toObject(includeInstance, f), evalEvent: (f = msg.getEvalEvent()) && node_pb.EvalEventMessage.toObject(includeInstance, f),
init: (f = msg.getInit()) && proto.WorkingInitMessage.toObject(includeInstance, f), init: (f = msg.getInit()) && proto.WorkingInitMessage.toObject(includeInstance, f),
sharedProcessActive: (f = msg.getSharedProcessActive()) && vscode_pb.SharedProcessActiveMessage.toObject(includeInstance, f) sharedProcessActive: (f = msg.getSharedProcessActive()) && vscode_pb.SharedProcessActiveMessage.toObject(includeInstance, f),
pong: (f = msg.getPong()) && node_pb.Pong.toObject(includeInstance, f)
}; };
if (includeInstance) { if (includeInstance) {
@@ -388,6 +435,11 @@ proto.ServerMessage.deserializeBinaryFromReader = function(msg, reader) {
reader.readMessage(value,vscode_pb.SharedProcessActiveMessage.deserializeBinaryFromReader); reader.readMessage(value,vscode_pb.SharedProcessActiveMessage.deserializeBinaryFromReader);
msg.setSharedProcessActive(value); msg.setSharedProcessActive(value);
break; break;
case 18:
var value = new node_pb.Pong;
reader.readMessage(value,node_pb.Pong.deserializeBinaryFromReader);
msg.setPong(value);
break;
default: default:
reader.skipField(); reader.skipField();
break; break;
@@ -457,6 +509,14 @@ proto.ServerMessage.serializeBinaryToWriter = function(message, writer) {
vscode_pb.SharedProcessActiveMessage.serializeBinaryToWriter vscode_pb.SharedProcessActiveMessage.serializeBinaryToWriter
); );
} }
f = message.getPong();
if (f != null) {
writer.writeMessage(
18,
f,
node_pb.Pong.serializeBinaryToWriter
);
}
}; };
@@ -610,6 +670,36 @@ proto.ServerMessage.prototype.hasSharedProcessActive = function() {
}; };
/**
* optional Pong pong = 18;
* @return {?proto.Pong}
*/
proto.ServerMessage.prototype.getPong = function() {
return /** @type{?proto.Pong} */ (
jspb.Message.getWrapperField(this, node_pb.Pong, 18));
};
/** @param {?proto.Pong|undefined} value */
proto.ServerMessage.prototype.setPong = function(value) {
jspb.Message.setOneofWrapperField(this, 18, proto.ServerMessage.oneofGroups_[0], value);
};
proto.ServerMessage.prototype.clearPong = function() {
this.setPong(undefined);
};
/**
* Returns whether this field is set.
* @return {!boolean}
*/
proto.ServerMessage.prototype.hasPong = function() {
return jspb.Message.getField(this, 18) != null;
};
/** /**
* Generated by JsPbCodeGenerator. * Generated by JsPbCodeGenerator.

View File

@@ -26,3 +26,7 @@ message EvalDoneMessage {
uint64 id = 1; uint64 id = 1;
string response = 2; string response = 2;
} }
message Ping {}
message Pong {}

View File

@@ -119,3 +119,35 @@ export namespace EvalDoneMessage {
} }
} }
export class Ping extends jspb.Message {
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): Ping.AsObject;
static toObject(includeInstance: boolean, msg: Ping): Ping.AsObject;
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
static serializeBinaryToWriter(message: Ping, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): Ping;
static deserializeBinaryFromReader(message: Ping, reader: jspb.BinaryReader): Ping;
}
export namespace Ping {
export type AsObject = {
}
}
export class Pong extends jspb.Message {
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): Pong.AsObject;
static toObject(includeInstance: boolean, msg: Pong): Pong.AsObject;
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
static serializeBinaryToWriter(message: Pong, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): Pong;
static deserializeBinaryFromReader(message: Pong, reader: jspb.BinaryReader): Pong;
}
export namespace Pong {
export type AsObject = {
}
}

View File

@@ -15,6 +15,8 @@ goog.exportSymbol('proto.EvalDoneMessage', null, global);
goog.exportSymbol('proto.EvalEventMessage', null, global); goog.exportSymbol('proto.EvalEventMessage', null, global);
goog.exportSymbol('proto.EvalFailedMessage', null, global); goog.exportSymbol('proto.EvalFailedMessage', null, global);
goog.exportSymbol('proto.NewEvalMessage', null, global); goog.exportSymbol('proto.NewEvalMessage', null, global);
goog.exportSymbol('proto.Ping', null, global);
goog.exportSymbol('proto.Pong', null, global);
/** /**
* Generated by JsPbCodeGenerator. * Generated by JsPbCodeGenerator.
@@ -843,4 +845,236 @@ proto.EvalDoneMessage.prototype.setResponse = function(value) {
}; };
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
* server response, or constructed directly in Javascript. The array is used
* in place and becomes part of the constructed object. It is not cloned.
* If no data is provided, the constructed object will be empty, but still
* valid.
* @extends {jspb.Message}
* @constructor
*/
proto.Ping = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.Ping, jspb.Message);
if (goog.DEBUG && !COMPILED) {
proto.Ping.displayName = 'proto.Ping';
}
if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto suitable for use in Soy templates.
* Field names that are reserved in JavaScript and will be renamed to pb_name.
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
* For the list of reserved names please see:
* com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
* @param {boolean=} opt_includeInstance Whether to include the JSPB instance
* for transitional soy proto support: http://goto/soy-param-migration
* @return {!Object}
*/
proto.Ping.prototype.toObject = function(opt_includeInstance) {
return proto.Ping.toObject(opt_includeInstance, this);
};
/**
* Static version of the {@see toObject} method.
* @param {boolean|undefined} includeInstance Whether to include the JSPB
* instance for transitional soy proto support:
* http://goto/soy-param-migration
* @param {!proto.Ping} msg The msg instance to transform.
* @return {!Object}
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.Ping.toObject = function(includeInstance, msg) {
var f, obj = {
};
if (includeInstance) {
obj.$jspbMessageInstance = msg;
}
return obj;
};
}
/**
* Deserializes binary data (in protobuf wire format).
* @param {jspb.ByteSource} bytes The bytes to deserialize.
* @return {!proto.Ping}
*/
proto.Ping.deserializeBinary = function(bytes) {
var reader = new jspb.BinaryReader(bytes);
var msg = new proto.Ping;
return proto.Ping.deserializeBinaryFromReader(msg, reader);
};
/**
* Deserializes binary data (in protobuf wire format) from the
* given reader into the given message object.
* @param {!proto.Ping} msg The message object to deserialize into.
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
* @return {!proto.Ping}
*/
proto.Ping.deserializeBinaryFromReader = function(msg, reader) {
while (reader.nextField()) {
if (reader.isEndGroup()) {
break;
}
var field = reader.getFieldNumber();
switch (field) {
default:
reader.skipField();
break;
}
}
return msg;
};
/**
* Serializes the message to binary data (in protobuf wire format).
* @return {!Uint8Array}
*/
proto.Ping.prototype.serializeBinary = function() {
var writer = new jspb.BinaryWriter();
proto.Ping.serializeBinaryToWriter(this, writer);
return writer.getResultBuffer();
};
/**
* Serializes the given message to binary data (in protobuf wire
* format), writing to the given BinaryWriter.
* @param {!proto.Ping} message
* @param {!jspb.BinaryWriter} writer
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.Ping.serializeBinaryToWriter = function(message, writer) {
var f = undefined;
};
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
* server response, or constructed directly in Javascript. The array is used
* in place and becomes part of the constructed object. It is not cloned.
* If no data is provided, the constructed object will be empty, but still
* valid.
* @extends {jspb.Message}
* @constructor
*/
proto.Pong = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.Pong, jspb.Message);
if (goog.DEBUG && !COMPILED) {
proto.Pong.displayName = 'proto.Pong';
}
if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto suitable for use in Soy templates.
* Field names that are reserved in JavaScript and will be renamed to pb_name.
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
* For the list of reserved names please see:
* com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
* @param {boolean=} opt_includeInstance Whether to include the JSPB instance
* for transitional soy proto support: http://goto/soy-param-migration
* @return {!Object}
*/
proto.Pong.prototype.toObject = function(opt_includeInstance) {
return proto.Pong.toObject(opt_includeInstance, this);
};
/**
* Static version of the {@see toObject} method.
* @param {boolean|undefined} includeInstance Whether to include the JSPB
* instance for transitional soy proto support:
* http://goto/soy-param-migration
* @param {!proto.Pong} msg The msg instance to transform.
* @return {!Object}
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.Pong.toObject = function(includeInstance, msg) {
var f, obj = {
};
if (includeInstance) {
obj.$jspbMessageInstance = msg;
}
return obj;
};
}
/**
* Deserializes binary data (in protobuf wire format).
* @param {jspb.ByteSource} bytes The bytes to deserialize.
* @return {!proto.Pong}
*/
proto.Pong.deserializeBinary = function(bytes) {
var reader = new jspb.BinaryReader(bytes);
var msg = new proto.Pong;
return proto.Pong.deserializeBinaryFromReader(msg, reader);
};
/**
* Deserializes binary data (in protobuf wire format) from the
* given reader into the given message object.
* @param {!proto.Pong} msg The message object to deserialize into.
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
* @return {!proto.Pong}
*/
proto.Pong.deserializeBinaryFromReader = function(msg, reader) {
while (reader.nextField()) {
if (reader.isEndGroup()) {
break;
}
var field = reader.getFieldNumber();
switch (field) {
default:
reader.skipField();
break;
}
}
return msg;
};
/**
* Serializes the message to binary data (in protobuf wire format).
* @return {!Uint8Array}
*/
proto.Pong.prototype.serializeBinary = function() {
var writer = new jspb.BinaryWriter();
proto.Pong.serializeBinaryToWriter(this, writer);
return writer.getResultBuffer();
};
/**
* Serializes the given message to binary data (in protobuf wire
* format), writing to the given BinaryWriter.
* @param {!proto.Pong} message
* @param {!jspb.BinaryWriter} writer
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.Pong.serializeBinaryToWriter = function(message, writer) {
var f = undefined;
};
goog.object.extend(exports, proto); goog.object.extend(exports, proto);

View File

@@ -1,5 +1,5 @@
import * as cp from "child_process"; import * as cp from "child_process";
import { logger, Logger, field, time } from "@coder/logger"; import {field, Logger, logger, time} from "@coder/logger";
export interface CommandResult { export interface CommandResult {
readonly exitCode: number; readonly exitCode: number;
@@ -9,7 +9,9 @@ export interface CommandResult {
const execute = (command: string, args: string[] = [], options: cp.SpawnOptions, logger: Logger): Promise<CommandResult> => { const execute = (command: string, args: string[] = [], options: cp.SpawnOptions, logger: Logger): Promise<CommandResult> => {
let resolve: (result: CommandResult) => void; let resolve: (result: CommandResult) => void;
const prom = new Promise<CommandResult>(res => resolve = res); const prom = new Promise<CommandResult>((res): void => {
resolve = res;
});
const stdout: string[] = []; const stdout: string[] = [];
const stderr: string[] = []; const stderr: string[] = [];
@@ -40,10 +42,12 @@ const execute = (command: string, args: string[] = [], options: cp.SpawnOptions,
return prom; return prom;
}; };
export type TaskFunction = (runner: Runner) => void | Promise<void>; // tslint:disable-next-line no-any
export type TaskFunction = (runner: Runner, ...args: any[]) => void | Promise<void>;
export interface Runner { export interface Runner {
cwd: string; cwd: string;
execute(command: string, args?: string[], env?: object): Promise<CommandResult>; execute(command: string, args?: string[], env?: object): Promise<CommandResult>;
} }
@@ -90,12 +94,24 @@ export const run = (name: string = process.argv[2]): void | Promise<void> => {
cwd = path; cwd = path;
}, },
execute(command: string, args: string[] = [], env?: object): Promise<CommandResult> { execute(command: string, args: string[] = [], env?: object): Promise<CommandResult> {
return execute(command, args, { const prom = execute(command, args, {
cwd, cwd,
env: env as NodeJS.ProcessEnv, env: env as NodeJS.ProcessEnv,
}, log); }, log);
return prom.then((result: CommandResult) => {
if (result.exitCode != 0) {
log.error("failed",
field("exitCode", result.exitCode),
field("stdout", result.stdout),
field("stderr", result.stderr)
);
}
return result;
});
}, },
}); }, ...process.argv.slice(3));
if (prom) { if (prom) {
activated.set(name, prom); activated.set(name, prom);

View File

@@ -14,16 +14,17 @@ fs.writeFileSync(shimPath, shimContent);
const nexe = require("nexe"); const nexe = require("nexe");
const target = `${os.platform()}-${os.arch()}`;
nexe.compile({ nexe.compile({
debugBundle: true, debugBundle: true,
input: path.join(__dirname, "../out/cli.js"), input: path.join(__dirname, "../out/cli.js"),
output: `cli-${process.env.TRAVIS_OS_NAME || os.platform()}`, output: `cli-${target}`,
targets: [os.platform()], targets: [target],
/** /**
* To include native extensions, do NOT install node_modules for each one. They * To include native extensions, do NOT install node_modules for each one. They
* are not required as each extension is built using webpack. * are not required as each extension is built using webpack.
*/ */
resources: [ resources: [
path.join(__dirname, "../package.json"), path.join(__dirname, "../package.json"),
path.join(__dirname, "../build/**/*"), path.join(__dirname, "../build/**/*"),
], ],

View File

@@ -2,6 +2,7 @@ import { field, logger } from "@coder/logger";
import { ServerMessage, SharedProcessActiveMessage } from "@coder/protocol/src/proto"; import { ServerMessage, SharedProcessActiveMessage } from "@coder/protocol/src/proto";
import { Command, flags } from "@oclif/command"; import { Command, flags } from "@oclif/command";
import { fork, ForkOptions, ChildProcess } from "child_process"; import { fork, ForkOptions, ChildProcess } from "child_process";
import { randomFillSync } from "crypto";
import * as fs from "fs"; import * as fs from "fs";
import * as os from "os"; import * as os from "os";
import * as path from "path"; import * as path from "path";
@@ -26,6 +27,7 @@ export class Entry extends Command {
version: flags.version({ char: "v" }), version: flags.version({ char: "v" }),
"no-auth": flags.boolean({ default: false }), "no-auth": flags.boolean({ default: false }),
"allow-http": flags.boolean({ default: false }), "allow-http": flags.boolean({ default: false }),
password: flags.string(),
// Dev flags // Dev flags
"bootstrap-fork": flags.string({ hidden: true }), "bootstrap-fork": flags.string({ hidden: true }),
@@ -113,7 +115,7 @@ export class Entry extends Command {
} }
} }
logger.info("\u001B[1mcode-server v1.0.0"); logger.info(`\u001B[1mcode-server ${process.env.VERSION ? `v${process.env.VERSION}` : "development"}`);
// TODO: fill in appropriate doc url // TODO: fill in appropriate doc url
logger.info("Additional documentation: http://github.com/codercom/code-server"); logger.info("Additional documentation: http://github.com/codercom/code-server");
logger.info("Initializing", field("data-dir", dataDir), field("working-dir", workingDir), field("log-dir", logDir)); logger.info("Initializing", field("data-dir", dataDir), field("working-dir", workingDir), field("log-dir", logDir));
@@ -132,13 +134,13 @@ export class Entry extends Command {
} }
}); });
const passwordLength = 12; let password = flags["password"];
const possible = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; if (!password) {
const chars = []; // Generate a random password
for (let i = 0; i < passwordLength; i++) { const buffer = Buffer.alloc(12);
chars.push(possible[Math.floor(Math.random() * possible.length)]); randomFillSync(buffer);
password = buffer.toString("hex");
} }
const password = chars.join("");
const hasCustomHttps = certData && certKeyData; const hasCustomHttps = certData && certKeyData;
const app = await createApp({ const app = await createApp({

View File

@@ -22,11 +22,15 @@ export const setup = (dataDirectory: string): void => {
return currentDir; return currentDir;
}, os.platform() === "win32" ? undefined! : path.sep); // Might need path.sep here for linux. Having it for windows causes an error because \C:\Users ... }, os.platform() === "win32" ? undefined! : path.sep); // Might need path.sep here for linux. Having it for windows causes an error because \C:\Users ...
const unpackModule = (moduleName: string): void => { const unpackModule = (moduleName: string, markExecutable: boolean = false): void => {
const memFile = path.join(isCli ? buildDir! : path.join(__dirname, ".."), "build/dependencies", moduleName); const memFile = path.join(isCli ? buildDir! : path.join(__dirname, ".."), "build/dependencies", moduleName);
const diskFile = path.join(dataDirectory, "dependencies", moduleName); const diskFile = path.join(dataDirectory, "dependencies", moduleName);
if (!fs.existsSync(diskFile)) { if (!fs.existsSync(diskFile)) {
fs.writeFileSync(diskFile, fs.readFileSync(memFile)); fs.writeFileSync(diskFile, fs.readFileSync(memFile));
if (markExecutable) {
fs.chmodSync(diskFile, "755");
}
} }
}; };
@@ -37,7 +41,7 @@ export const setup = (dataDirectory: string): void => {
*/ */
unpackModule("pty.node"); unpackModule("pty.node");
unpackModule("spdlog.node"); unpackModule("spdlog.node");
unpackModule("rg"); unpackModule("rg", true);
// const nodePtyUtils = require("../../protocol/node_modules/node-pty-prebuilt/lib/utils") as typeof import("../../protocol/node_modules/node-pty-prebuilt/src/utils"); // const nodePtyUtils = require("../../protocol/node_modules/node-pty-prebuilt/lib/utils") as typeof import("../../protocol/node_modules/node-pty-prebuilt/src/utils");
// tslint:disable-next-line:no-any // tslint:disable-next-line:no-any
// nodePtyUtils.loadNative = (modName: string): any => { // nodePtyUtils.loadNative = (modName: string): any => {

View File

@@ -1,5 +1,4 @@
#!/bin/bash #!/bin/bash
set -e set -e
npm install -g cross-env
yarn task build:server:binary yarn task build:server:binary

View File

@@ -2,7 +2,7 @@ import { exec, execSync } from "child_process";
import { existsSync, readdirSync } from "fs"; import { existsSync, readdirSync } from "fs";
import * as os from "os"; import * as os from "os";
import { join, resolve } from "path"; import { join, resolve } from "path";
import { logger, field } from "../packages/logger"; import { logger, field } from "../packages/logger/src/logger";
/** /**
* Install dependencies for a single package. * Install dependencies for a single package.

View File

@@ -31,7 +31,7 @@ index 1922450144..9900776aa2 100644
-import { isMacintosh } from 'vs/base/common/platform'; -import { isMacintosh } from 'vs/base/common/platform';
+import { isMacintosh } from 'vs/base/browser/browser'; +import { isMacintosh } from 'vs/base/browser/browser';
diff --git a/src/vs/base/browser/ui/list/listWidget.ts b/src/vs/base/browser/ui/list/listWidget.ts diff --git a/src/vs/base/browser/ui/list/listWidget.ts b/src/vs/base/browser/ui/list/listWidget.ts
index 5386958054..5c936e0a1d 100644 index e6b2e4e39b..06cdfe152f 100644
--- a/src/vs/base/browser/ui/list/listWidget.ts --- a/src/vs/base/browser/ui/list/listWidget.ts
+++ b/src/vs/base/browser/ui/list/listWidget.ts +++ b/src/vs/base/browser/ui/list/listWidget.ts
@@ -13 +13 @@ import * as DOM from 'vs/base/browser/dom'; @@ -13 +13 @@ import * as DOM from 'vs/base/browser/dom';
@@ -43,7 +43,7 @@ index 5386958054..5c936e0a1d 100644
@@ -479 +479 @@ export function isSelectionSingleChangeEvent(event: IListMouseEvent<any> | IList @@ -479 +479 @@ export function isSelectionSingleChangeEvent(event: IListMouseEvent<any> | IList
- return platform.isMacintosh ? event.browserEvent.metaKey : event.browserEvent.ctrlKey; - return platform.isMacintosh ? event.browserEvent.metaKey : event.browserEvent.ctrlKey;
+ return browser.isMacintosh ? event.browserEvent.metaKey : event.browserEvent.ctrlKey; + return browser.isMacintosh ? event.browserEvent.metaKey : event.browserEvent.ctrlKey;
@@ -539 +539 @@ class MouseController<T> implements IDisposable { @@ -540 +540 @@ class MouseController<T> implements IDisposable {
- return platform.isMacintosh ? event.browserEvent.metaKey : event.browserEvent.ctrlKey; - return platform.isMacintosh ? event.browserEvent.metaKey : event.browserEvent.ctrlKey;
+ return browser.isMacintosh ? event.browserEvent.metaKey : event.browserEvent.ctrlKey; + return browser.isMacintosh ? event.browserEvent.metaKey : event.browserEvent.ctrlKey;
diff --git a/src/vs/base/browser/ui/sash/sash.ts b/src/vs/base/browser/ui/sash/sash.ts diff --git a/src/vs/base/browser/ui/sash/sash.ts b/src/vs/base/browser/ui/sash/sash.ts
@@ -91,7 +91,7 @@ index 01f59d40fa..453d5c4ed3 100644
-import { isMacintosh } from 'vs/base/common/platform'; -import { isMacintosh } from 'vs/base/common/platform';
+import { isMacintosh } from 'vs/base/browser/browser'; +import { isMacintosh } from 'vs/base/browser/browser';
diff --git a/src/vs/base/browser/ui/tree/abstractTree.ts b/src/vs/base/browser/ui/tree/abstractTree.ts diff --git a/src/vs/base/browser/ui/tree/abstractTree.ts b/src/vs/base/browser/ui/tree/abstractTree.ts
index 742c6aa0d8..2791d0691e 100644 index d9665944a1..80659bb5f0 100644
--- a/src/vs/base/browser/ui/tree/abstractTree.ts --- a/src/vs/base/browser/ui/tree/abstractTree.ts
+++ b/src/vs/base/browser/ui/tree/abstractTree.ts +++ b/src/vs/base/browser/ui/tree/abstractTree.ts
@@ -24 +24 @@ import { disposableTimeout } from 'vs/base/common/async'; @@ -24 +24 @@ import { disposableTimeout } from 'vs/base/common/async';
@@ -685,7 +685,7 @@ index 6d25977a66..788f5c96e7 100644
- return `${product.extensionsGallery.itemUrl}?itemName=${this.publisher}.${this.name}`; - return `${product.extensionsGallery.itemUrl}?itemName=${this.publisher}.${this.name}`;
+ return undefined; // `${product.extensionsGallery.itemUrl}?itemName=${this.publisher}.${this.name}`; + return undefined; // `${product.extensionsGallery.itemUrl}?itemName=${this.publisher}.${this.name}`;
diff --git a/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.ts b/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.ts diff --git a/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.ts b/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.ts
index 1002950c75..8c187d36ff 100644 index 9df71eeec1..c68c42e922 100644
--- a/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.ts --- a/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.ts
+++ b/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.ts +++ b/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.ts
@@ -17 +17 @@ import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/co @@ -17 +17 @@ import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/co
@@ -699,13 +699,13 @@ index 0bd9b93fcc..1c8adeb5ca 100644
-import { isWindows, isMacintosh } from 'vs/base/common/platform'; -import { isWindows, isMacintosh } from 'vs/base/common/platform';
+import { isWindows, isMacintosh } from 'vs/base/browser/browser'; +import { isWindows, isMacintosh } from 'vs/base/browser/browser';
diff --git a/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.ts diff --git a/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.ts
index e66f74f034..e2c24d851a 100644 index 45b32eec0a..1f58bdcd70 100644
--- a/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.ts --- a/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.ts
+++ b/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.ts
@@ -39 +39 @@ import { DesktopDragAndDropData, ExternalElementsDragAndDropData, ElementsDragAn @@ -39 +39 @@ import { DesktopDragAndDropData, ExternalElementsDragAndDropData, ElementsDragAn
-import { isMacintosh, isLinux } from 'vs/base/common/platform'; -import { isMacintosh, isLinux } from 'vs/base/common/platform';
+import { isMacintosh, isLinux } from 'vs/base/browser/browser'; +import { isMacintosh, isLinux } from 'vs/base/browser/browser';
@@ -586,0 +587 @@ export class FileDragAndDrop implements ITreeDragAndDrop<ExplorerItem> { @@ -591,0 +592 @@ export class FileDragAndDrop implements ITreeDragAndDrop<ExplorerItem> {
+ return (require('vs/../../../../packages/vscode/src/workbench') as typeof import('vs/../../../../packages/vscode/src/workbench')).workbench.handleExternalDrop(target, originalEvent); + return (require('vs/../../../../packages/vscode/src/workbench') as typeof import('vs/../../../../packages/vscode/src/workbench')).workbench.handleExternalDrop(target, originalEvent);
diff --git a/src/vs/workbench/parts/logs/electron-browser/logs.contribution.ts b/src/vs/workbench/parts/logs/electron-browser/logs.contribution.ts diff --git a/src/vs/workbench/parts/logs/electron-browser/logs.contribution.ts b/src/vs/workbench/parts/logs/electron-browser/logs.contribution.ts
index 4015c9cd5d..bebdb25f6c 100644 index 4015c9cd5d..bebdb25f6c 100644
@@ -854,13 +854,13 @@ index 033bd98d00..ba776c5ff3 100644
-import { isMacintosh } from 'vs/base/common/platform'; -import { isMacintosh } from 'vs/base/common/platform';
+import { isMacintosh } from 'vs/base/browser/browser'; +import { isMacintosh } from 'vs/base/browser/browser';
diff --git a/src/vs/workbench/parts/webview/electron-browser/webviewElement.ts b/src/vs/workbench/parts/webview/electron-browser/webviewElement.ts diff --git a/src/vs/workbench/parts/webview/electron-browser/webviewElement.ts b/src/vs/workbench/parts/webview/electron-browser/webviewElement.ts
index 5d9110300f..eb16014814 100644 index d8de423529..5953e920c3 100644
--- a/src/vs/workbench/parts/webview/electron-browser/webviewElement.ts --- a/src/vs/workbench/parts/webview/electron-browser/webviewElement.ts
+++ b/src/vs/workbench/parts/webview/electron-browser/webviewElement.ts +++ b/src/vs/workbench/parts/webview/electron-browser/webviewElement.ts
@@ -21 +21 @@ import { endsWith } from 'vs/base/common/strings'; @@ -21 +21 @@ import { endsWith } from 'vs/base/common/strings';
-import { isMacintosh } from 'vs/base/common/platform'; -import { isMacintosh } from 'vs/base/common/platform';
+import { isMacintosh } from 'vs/base/browser/browser'; +import { isMacintosh } from 'vs/base/browser/browser';
@@ -261,0 +262,3 @@ export class WebviewElement extends Disposable { @@ -265,0 +266,3 @@ export class WebviewElement extends Disposable {
+ Object.defineProperty(this._options, 'useSameOriginForRoot', { + Object.defineProperty(this._options, 'useSameOriginForRoot', {
+ value: true, + value: true,
+ }); + });

View File

@@ -105,7 +105,7 @@ module.exports = (options = {}) => ({
plugins: [ plugins: [
new HappyPack({ new HappyPack({
id: "ts", id: "ts",
threads: os.cpus().length - 1, threads: Math.max(os.cpus().length - 1, 1),
loaders: [{ loaders: [{
path: "ts-loader", path: "ts-loader",
query: { query: {
@@ -118,6 +118,7 @@ module.exports = (options = {}) => ({
"process.env.NODE_ENV": `"${environment}"`, "process.env.NODE_ENV": `"${environment}"`,
"process.env.LOG_LEVEL": `"${process.env.LOG_LEVEL || ""}"`, "process.env.LOG_LEVEL": `"${process.env.LOG_LEVEL || ""}"`,
"process.env.SERVICE_URL": `"${process.env.SERVICE_URL || ""}"`, "process.env.SERVICE_URL": `"${process.env.SERVICE_URL || ""}"`,
"process.env.VERSION": `"${process.env.VERSION || ""}"`,
}), }),
], ],
stats: { stats: {