Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
baa48c8
Scaffold chrome e2e tests
Mar 27, 2019
b7c9a79
Just use http for tests
Mar 27, 2019
45f24a5
Generalize page loading
Mar 27, 2019
6a639dc
Move e2e tests to root test dir
Mar 27, 2019
4ff89b6
Update docs and killProcesses accessibility
Mar 27, 2019
4cc8209
Add file creation test
Mar 27, 2019
1f3ee75
Clarify docs for loading headless pages
Mar 27, 2019
896f719
Update open-IDE and file-creation tests to verify DOM
Mar 28, 2019
f2fa826
Add type definition for deserialized HTML elements
Mar 29, 2019
bcca444
Use platform specific keybind for opening palette
Mar 29, 2019
6217b8b
Add delete file test
Mar 29, 2019
e8b4d67
Use LOG_LEVEL env to debug puppeteer tests
Mar 29, 2019
798dc03
Add open file test
Mar 29, 2019
181be98
Add extension installation test
Mar 29, 2019
60092ae
Add extension uninstall test
Mar 29, 2019
22314d3
Abstract combination keyboard shortcuts
Mar 29, 2019
bb00fd9
Add debug file test
Mar 29, 2019
8fa7500
Add --port and --password tests
Apr 1, 2019
36fda5f
Add stderr listener
Apr 2, 2019
4c051c0
Add end-to-end testing task for CI
Apr 2, 2019
aa07908
Add libnss3 req for puppeteer on trusty
Apr 5, 2019
0460251
Add support for setuid sandbox
Apr 5, 2019
1a7aa5c
Add common ubuntu deps for puppeteer to CI
Apr 5, 2019
2962b8d
Enable user namespace cloning
Apr 5, 2019
d66f023
Disable sandboxing
Apr 8, 2019
58afa93
Don't overload gcc dep
Apr 9, 2019
e49cefb
Default to Docker for non-mac CI e2e tests
Apr 9, 2019
3f3a648
Increase startup test timeout and remove waitFor
Apr 9, 2019
c5d2e7a
Make default CLI path generic
Apr 9, 2019
deb86e2
Fix puppeteer not clicking move-to-trash button
Apr 10, 2019
694b848
Update yarn lock
Apr 17, 2019
574eec5
Update tests node version to 10.15.1
Apr 17, 2019
00cbe2b
Don't throw when child writes to stderr
Apr 18, 2019
2cf17bc
Focus sidebar to create file via palette
Apr 18, 2019
dbca98b
Fix @coder/logger mapping
Apr 18, 2019
5a43005
Install test/ dependencies with packages/
Apr 18, 2019
d2a85ba
Use page.click instead of page.$eval
Apr 18, 2019
32c3f3d
Set default jest timeouts
Apr 19, 2019
1daed23
Fix open-file and debug-file tests
Apr 19, 2019
e74c9a3
Fix file-tree loading slowly for tests in Docker
Apr 19, 2019
7c5b14b
Revert "Use page.click instead of page.$eval"
Apr 19, 2019
83caa24
Fix command palette by first focusing an element
Apr 19, 2019
8ee3a41
Switch ports to debug CI
Apr 20, 2019
a75aac1
Remove sub domains from test hostname
Apr 20, 2019
bcb434b
Don't wait for non-existant file in tree
Apr 20, 2019
ca3f0b4
Allow exec SIGTERM to cascade for tests
Apr 20, 2019
1fa3df2
Use child_process spawn instead of exec
Apr 20, 2019
79245e6
Convert stderr chunks to string
Apr 22, 2019
6f5f51a
Cleanup child processes upon SIGTERM
Apr 22, 2019
35ae078
fixup! Cleanup child processes upon SIGTERM
Apr 22, 2019
712f24a
Fix install extension test button not clicking
Apr 23, 2019
2f408d9
Use click() instead of MouseEvent to delete file
Apr 23, 2019
71922ea
Minimize puppeteer timeouts
Apr 23, 2019
2ee47d2
Test creating file from file-tree and setup files
Apr 23, 2019
1ac9db8
Update CI test script
Apr 24, 2019
db2298e
Use jest directly to correct I/O perm issues
Apr 24, 2019
e19ce0f
Wait for editor instead of tab when opening file
Apr 24, 2019
bb15e38
Screenshot puppeteer actions for logging purposes
Apr 25, 2019
a77b72a
Reduce screenshots to resonable amount
Apr 25, 2019
c8257e3
Scaffold bucket uploader for e2e CI-screenshots
Apr 25, 2019
8826f70
Use encrypted file to define GCP credentials on CI
Apr 25, 2019
3d5cbaa
Remove gcloud test in favor of e2e tests
Apr 26, 2019
20aec40
Use Travis unique job num instead of build num
Apr 26, 2019
4769792
Make screenshots public by default
Apr 26, 2019
4e1da62
Make custom unique job ID for Travis
Apr 26, 2019
9505274
Use unix timestamp for cross platform compat
Apr 26, 2019
b9a7c84
Update screenshot MIME type for previewing
Apr 26, 2019
3dca888
Pass CI env vars to docker image
Apr 26, 2019
1d7c34a
Group stored screenshots by server
Apr 26, 2019
6e30eb9
Update docker env vars before running tests
Apr 26, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@ language: node_js
node_js:
- 10.15.1
env:
matrix:
- VSCODE_VERSION="1.33.1" MAJOR_VERSION="1" VERSION="$MAJOR_VERSION.$TRAVIS_BUILD_NUMBER-vsc$VSCODE_VERSION"
matrix:
include:
- os: linux
dist: trusty
- os: osx
before_install:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install libxkbfile-dev
libsecret-1-dev; fi
- openssl aes-256-cbc -K $encrypted_31e0a178b4fd_key -iv $encrypted_31e0a178b4fd_iv
-in test/.coder-gcp-credentials.json.enc -out test/.coder-gcp-credentials.json -d
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
sudo apt-get install -y libxkbfile-dev libsecret-1-dev; fi
- npm install -g yarn@1.12.3
script:
- scripts/build.sh
Expand All @@ -31,13 +34,13 @@ deploy:
api_key:
secure: YL/x24KjYjgYXPcJWk3FV7FGxI79Mh6gBECQEcdlf3fkLEoKFVgzHBoUNWrFPzyR4tgLyWNAgcpD9Lkme1TRWTom7UPjXcwMNyLcLa+uec7ciSAnYD9ntLTpiCuPDD1u0LtRGclSi/EHQ+F8YVq+HZJpXTsJeAmOmihma3GVbGKSZr+BRum+0YZSG4w+o4TOlYzw/4bLWS52MogZcwpjd+hemBbgXLuGU2ziKv2vEKCZFbEeA16II4x1WLI4mutDdCeh7+3aLzGLwDa49NxtsVYNjyNFF75JhCTCNA55e2YMiLz9Uq69IXe/mi5F7xUaFfhIqqLNyKBnKeEOzu3dYnc+8n3LjnQ+00PmkF05nx9kBn3UfV1kwQGh6QbyDmTtBP07rtUMyI14aeQqHjxsaVRdMnwj9Q2DjXRr8UDqESZF0rmK3pHCXS2fBhIzLE8tLVW5Heiba2pQRFMHMZW+KBE97FzcFh7is90Ait3T8enfcd/PWFPYoBejDAdjwxwOkezh5N5ZkYquEfDYuWrFi6zRFCktsruaAcA+xGtTf9oilBBzUqu8Ie+YFWH5me83xakcblJWdaW/D2rLJAJH3m6LFm8lBqyUgDX5t/etob6CpDuYHu5D1J3XINOj/+aLAcadq6qlh70PMZS3zYffUu3JlzaD2amlSHIT8b5YXFc=
file:
- release/*.tar.gz
- release/*.zip
- release/*.tar.gz
- release/*.zip
on:
repo: codercom/code-server
branch: master
cache:
yarn: true
timeout: 1000
directories:
- .cache
- ".cache"
21 changes: 20 additions & 1 deletion build/tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const defaultExtensionsPath = path.join(libPath, "extensions");
const pkgsPath = path.join(__dirname, "../packages");
const vscodeVersion = process.env.VSCODE_VERSION || "1.33.1";
const vsSourceUrl = `https://codesrv-ci.cdr.sh/vstar-${vscodeVersion}.tar.gz`;
const binaryPath = path.join(__dirname, `../packages/server/cli-${os.platform()}-${os.arch()}`);

const buildServerBinary = register("build:server:binary", async (runner) => {
await ensureInstalled();
Expand Down Expand Up @@ -185,7 +186,6 @@ register("package", async (runner, releaseTag) => {
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");
Expand All @@ -199,4 +199,23 @@ register("package", async (runner, releaseTag) => {
: runner.execute("zip", ["-r", `${archiveName}.zip`, `${archiveName}`]));
});

register("test:e2e", async (runner) => {
if (!fs.existsSync(binaryPath)) {
throw new Error("Binary must be built to test");
}

const test = await runner.execute(
isWin ? "npm.cmd" : "npm",
[
"--scripts-prepend-node-path",
"--",
"run",
"test:e2e",
],
);
if (test.exitCode !== 0) {
throw new Error(`Tests failed: \n${test.stderr}`);
}
});

run();
51 changes: 51 additions & 0 deletions code-server-e2e.dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
FROM node:10.15.1

# Install puppeteer deps.
RUN apt-get update && apt-get install -qy gconf-service \
libnss3 \
libasound2 \
libatk1.0-0 \
libatk-bridge2.0-0 \
libcairo2 \
libcups2 \
libdbus-1-3 \
libexpat1 \
libfontconfig1 \
libgconf-2-4 \
libgdk-pixbuf2.0-0 \
libglib2.0-0 \
libgtk-3-0 \
libnspr4 \
libpango-1.0-0 \
libpangocairo-1.0-0 \
libx11-6 \
libx11-xcb1 \
libxcb1 \
libxcomposite1 \
libxcursor1 \
libxdamage1 \
libxext6 \
libxfixes3 \
libxi6 \
libxrandr2 \
libxrender1 \
libxss1 \
libxtst6 \
ca-certificates \
fonts-liberation \
libappindicator1 \
lsb-release \
xdg-utils \
wget

# Get libc6 v2.28.x
RUN echo "deb http://ftp.de.debian.org/debian buster main" >> /etc/apt/sources.list && \
apt-get update && \
apt-get install -y libc6

# Ensure that yarn is installed.
RUN npm i -g yarn@1.12.3 npx

# Copy CI environment variables, if they exist.
ARG env_vars
RUN if [ "$env_vars" != "" ]; then echo $env_vars | base64 -d >> ~/.bashrc && . ~/.bashrc; fi
9 changes: 7 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"postinstall": "npm-run-all --parallel packages:install build:rules",
"start": "cd ./packages/server && yarn start",
"task": "ts-node -r tsconfig-paths/register build/tasks.ts",
"test": "cd ./packages && yarn test"
"test": "cd ./packages && yarn test",
"test:e2e": "cd ./test && yarn test"
},
"devDependencies": {
"@types/fs-extra": "^5.0.4",
Expand All @@ -28,16 +29,19 @@
"html-webpack-plugin": "^3.2.0",
"http-browserify": "^1.7.0",
"ignore-loader": "^0.1.2",
"jest": "^24.7.1",
"mini-css-extract-plugin": "^0.5.0",
"node-sass": "^4.11.0",
"npm-run-all": "^4.1.5",
"path-browserify": "^1.0.0",
"preload-webpack-plugin": "^3.0.0-beta.2",
"puppeteer": "^1.14.0",
"sass-loader": "^7.1.0",
"string-replace-loader": "^2.1.1",
"style-loader": "^0.23.1",
"tar": "^4.4.8",
"terser-webpack-plugin": "^1.2.3",
"ts-jest": "^24.0.2",
"ts-loader": "^5.3.3",
"ts-node": "^7.0.1",
"tsconfig-paths": "^3.8.0",
Expand All @@ -56,7 +60,8 @@
"webpack-hot-middleware": "^2.24.3",
"webpack-pwa-manifest": "^4.0.0",
"workbox-webpack-plugin": "^4.1.0",
"write-file-webpack-plugin": "^4.5.0"
"write-file-webpack-plugin": "^4.5.0",
"xml2js": "^0.4.19"
},
"resolutions": {
"bindings": "1.3.0"
Expand Down
2 changes: 1 addition & 1 deletion packages/app/chrome/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
"scripts": {
"build": "../../../node_modules/.bin/webpack --config ./webpack.config.js"
}
}
}
8 changes: 3 additions & 5 deletions packages/package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
{
"scripts": {
"postinstall": "../node_modules/.bin/ts-node ../scripts/install-packages.ts",
"test": "jest"
"test": "npx jest --verbose"
},
"devDependencies": {
"@types/jest": "^23.3.12",
"jest": "^23.6.0",
"ts-jest": "^23.10.5"
"@types/jest": "^23.3.12"
},
"dependencies": {
"xmlhttprequest": "1.8.0"
Expand Down Expand Up @@ -44,4 +42,4 @@
],
"testRegex": ".*\\.test\\.tsx?"
}
}
}
12 changes: 10 additions & 2 deletions packages/protocol/src/node/modules/child_process.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { WritableProxy, ReadableProxy } from "./stream";
export type ForkProvider = (modulePath: string, args?: string[], options?: cp.ForkOptions) => cp.ChildProcess;

export class ChildProcessProxy implements ServerProxy {
public constructor(private readonly process: cp.ChildProcess) {}
public constructor(private readonly process: cp.ChildProcess) { }

public async kill(signal?: string): Promise<void> {
this.process.kill(signal);
Expand Down Expand Up @@ -70,7 +70,8 @@ export interface ChildProcessProxies {
}

export class ChildProcessModuleProxy {
public constructor(private readonly forkProvider?: ForkProvider) {}
public readonly processes: Map<number, cp.ChildProcess> = new Map();
public constructor(private readonly forkProvider?: ForkProvider) { }

public async exec(
command: string,
Expand All @@ -94,7 +95,14 @@ export class ChildProcessModuleProxy {
return this.returnProxies(cp.spawn(command, args, options));
}

public async dispose(): Promise<void> {
this.processes.forEach((p) => p.kill("SIGTERM"));
}

private returnProxies(process: cp.ChildProcess): ChildProcessProxies {
process.on("exit", () => this.processes.delete(process.pid));
this.processes.set(process.pid, process);

return {
childProcess: new ChildProcessProxy(process),
stdin: process.stdin && new WritableProxy(process.stdin),
Expand Down
12 changes: 6 additions & 6 deletions packages/protocol/src/node/server.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { mkdirp } from "fs-extra";
import * as os from "os";
import { field, logger} from "@coder/logger";
import { field, logger } from "@coder/logger";
import { ReadWriteConnection } from "../common/connection";
import { Module, ServerProxy } from "../common/proxy";
import { isPromise, isProxy, moduleToProto, protoToArgument, platformToProto, protoToModule, argumentToProto } from "../common/util";
Expand Down Expand Up @@ -60,8 +60,8 @@ export class Server {
]);

this.proxies.forEach((proxy, proxyId) => {
if (isProxy(proxy.instance)) {
proxy.instance.dispose().catch((error) => {
if (typeof proxy.instance.dispose === "function") {
(proxy.instance.dispose() as Promise<void>).catch((error) => {
logger.error(error.message);
});
}
Expand Down Expand Up @@ -196,7 +196,7 @@ export class Server {
callbackMessage = new Callback.Named();
callbackMessage.setModule(moduleToProto(proxyId));
message.setNamedCallback(callbackMessage);
} else {
} else {
callbackMessage = new Callback.Numbered();
callbackMessage.setProxyId(proxyId);
message.setNumberedCallback(callbackMessage);
Expand Down Expand Up @@ -279,7 +279,7 @@ export class Server {
eventMessage = new Event.Named();
eventMessage.setModule(moduleToProto(proxyId));
message.setNamedEvent(eventMessage);
} else {
} else {
eventMessage = new Event.Numbered();
eventMessage.setProxyId(proxyId);
message.setNumberedEvent(eventMessage);
Expand Down Expand Up @@ -316,7 +316,7 @@ export class Server {
private sendException(id: number, error: Error): void {
logger.trace(() => [
"sending reject",
field("id", id) ,
field("id", id),
field("message", error.message),
]);

Expand Down
17 changes: 11 additions & 6 deletions packages/server/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import * as os from "os";
import * as path from "path";
import * as WebSocket from "ws";
import { buildDir, cacheHome, dataHome, isCli, serveStatic } from "./constants";
import { createApp } from "./server";
import { createApp, connections } from "./server";
import { forkModule, requireModule } from "./vscode/bootstrapFork";
import { SharedProcess, SharedProcessState } from "./vscode/sharedProcess";
import opn = require("opn");
Expand Down Expand Up @@ -178,11 +178,11 @@ const bold = (text: string | number): string | number => {
"--extensions-dir", extensionsDir,
"--install-extension", options.installExtension,
], {
env: {
VSCODE_ALLOW_IO: "true",
VSCODE_LOGS: process.env.VSCODE_LOGS,
},
}, dataDir);
env: {
VSCODE_ALLOW_IO: "true",
VSCODE_LOGS: process.env.VSCODE_LOGS,
},
}, dataDir);

fork.stdout.on("data", (d: Buffer) => d.toString().split("\n").forEach((l) => logger.info(l)));
fork.stderr.on("data", (d: Buffer) => d.toString().split("\n").forEach((l) => logger.error(l)));
Expand Down Expand Up @@ -265,6 +265,11 @@ const bold = (text: string | number): string | number => {
cert: certData,
} : undefined,
});
process.on("SIGTERM", () => {
connections.forEach((c) => c.close());
sharedProcess.dispose();
process.exit(1);
});

logger.info("Starting webserver...", field("host", options.host), field("port", options.port));
app.server.listen(options.port, options.host);
Expand Down
12 changes: 10 additions & 2 deletions packages/server/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,13 @@ interface CreateAppOptions {
bypassAuth?: boolean;
}

let connectionID = 0;
export const connections: Map<number, ReadWriteConnection> = new Map();

export const createApp = async (options: CreateAppOptions): Promise<{
readonly express: express.Application;
readonly server: http.Server;
readonly wss: ws.Server;
readonly wss: ws.Server
}> => {
const parseCookies = (req: http.IncomingMessage): { [key: string]: string } => {
const cookies: { [key: string]: string } = {};
Expand Down Expand Up @@ -166,6 +169,7 @@ export const createApp = async (options: CreateAppOptions): Promise<{
return ws.send(JSON.stringify({ ports: portScanner.ports }));
}

const localConnectionID = connectionID++;
const connection: ReadWriteConnection = {
onMessage: (cb): void => {
ws.addEventListener("message", (event) => cb(event.data));
Expand All @@ -183,8 +187,12 @@ export const createApp = async (options: CreateAppOptions): Promise<{
},
onUp: (): void => undefined, // This can't come back up.
onDown: (cb): void => ws.addEventListener("close", () => cb()),
onClose: (cb): void => ws.addEventListener("close", () => cb()),
onClose: (cb): void => ws.addEventListener("close", () => {
connections.delete(localConnectionID);
cb();
}),
};
connections.set(localConnectionID, connection);

// tslint:disable-next-line no-unused-expression
new Server(connection, options.serverOptions);
Expand Down
4 changes: 4 additions & 0 deletions packages/server/src/vscode/sharedProcess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ export class SharedProcess {
this.ipcHandler.send("handshake:goodbye");
}
this.ipcHandler = undefined;
retry.block();
if (this.activeProcess && !this.activeProcess.killed) {
this.activeProcess.kill("SIGTERM");
}
}

/**
Expand Down
Loading