@andersbakken/fisk 3.5.6 → 3.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,36 +1,70 @@
1
1
  {
2
- "name": "@andersbakken/fisk",
3
- "version": "3.5.6",
4
- "description": "Fisk, a distributed compile system",
5
- "scripts": {
6
- "test": "echo \"Error: no test specified\" && exit 1"
7
- },
8
- "repository": {
9
- "type": "git",
10
- "url": "git+https://github.com/Andersbakken/fisk.git"
11
- },
12
- "author": "",
13
- "license": "ISC",
14
- "bugs": {
15
- "url": "https://github.com/Andersbakken/fisk/issues"
16
- },
17
- "homepage": "https://github.com/Andersbakken/fisk#readme",
18
- "dependencies": {
19
- "@jhanssen/options": "^1.0.25",
20
- "axios": "^0.21.1",
21
- "blessed": "^0.1.81",
22
- "bytes": "^3.0.0",
23
- "compare-versions": "^3.4.0",
24
- "express": "^4.16.3",
25
- "fs-extra": "^6.0.1",
26
- "humanize-duration": "^3.17.0",
27
- "lowdb": "^1.0.0",
28
- "minimist": "^1.2.5",
29
- "mktemp": "^0.4.0",
30
- "parse-duration": "^0.1.1",
31
- "posix": "^4.2.0",
32
- "prettysize": "^2.0.0",
33
- "wake_on_lan": "^1.0.0",
34
- "ws": "^7.4.6"
35
- }
2
+ "name": "@andersbakken/fisk",
3
+ "version": "3.6.0",
4
+ "description": "Fisk, a distributed compile system",
5
+ "scripts": {
6
+ "lint": "eslint . --ext .ts",
7
+ "rollup": "rollup -c",
8
+ "tsc": "tsc -p .",
9
+ "build": "npm run clean:dist && mkdir -p dist && run-p lint rollup",
10
+ "clean:dist": "del-cli dist/*",
11
+ "clean:cache": "del-cli .cache/*",
12
+ "clean": "run-p clean:dist clean:cache",
13
+ "watch": "rollup -c -w"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/Andersbakken/fisk.git"
18
+ },
19
+ "author": "",
20
+ "license": "ISC",
21
+ "bugs": {
22
+ "url": "https://github.com/Andersbakken/fisk/issues"
23
+ },
24
+ "homepage": "https://github.com/Andersbakken/fisk#readme",
25
+ "files": ["dist/*.js", "dist/*.js.map"],
26
+ "dependencies": {
27
+ "@jhanssen/options": "^1.0.34",
28
+ "@josh_stern/mktemp": "^1.0.5",
29
+ "axios": "^0.21.1",
30
+ "blessed": "^0.1.81",
31
+ "bufferutil": "^4.0.7",
32
+ "bytes": "^3.0.0",
33
+ "chroot": "^1.0.11",
34
+ "compare-versions": "^3.4.0",
35
+ "express": "^4.18.2",
36
+ "fs-extra": "^6.0.1",
37
+ "humanize-duration": "^3.17.0",
38
+ "lowdb": "^1.0.0",
39
+ "minimist": "^1.2.5",
40
+ "parse-duration": "^1.0.2",
41
+ "posix": "^4.2.0",
42
+ "pretty-bytes": "^6.0.0",
43
+ "typescript": "^4.3.5",
44
+ "utf-8-validate": "^5.0.10",
45
+ "ws": "^7.4.6"
46
+ },
47
+ "devDependencies": {
48
+ "@rollup/plugin-commonjs": "^24.0.1",
49
+ "@rollup/plugin-json": "^6.0.0",
50
+ "@rollup/plugin-node-resolve": "^13.0.6",
51
+ "@rollup/plugin-replace": "^2.3.4",
52
+ "@types/bytes": "^3.1.1",
53
+ "@types/express": "^4.17.13",
54
+ "@types/fs-extra": "^9.0.13",
55
+ "@types/humanize-duration": "^3.27.1",
56
+ "@types/node": "^14.14.25",
57
+ "@types/posix": "^4.2.0",
58
+ "@types/ws": "^8.5.3",
59
+ "@typescript-eslint/eslint-plugin": "^4.14.2",
60
+ "@typescript-eslint/parser": "^4.14.2",
61
+ "del-cli": "^3.0.1",
62
+ "eslint": "^7.19.0",
63
+ "eslint-plugin-sort-imports-es6-autofix": "^0.5.0",
64
+ "npm-run-all": "^4.1.5",
65
+ "prettier": "^2.2.1",
66
+ "rollup": "^2.38.4",
67
+ "rollup-plugin-hashbang": "^3.0.0",
68
+ "rollup-plugin-typescript2": "^0.27.0"
69
+ }
36
70
  }
package/builder/VM.js DELETED
@@ -1,156 +0,0 @@
1
- /* global quitOnError */
2
- const EventEmitter = require('events');
3
- const child_process = require('child_process');
4
- const fs = require('fs-extra');
5
- const path = require('path');
6
- let quitOnError;
7
-
8
- class CompileJob extends EventEmitter
9
- {
10
- constructor(commandLine, argv0, id, vm) {
11
- super();
12
- this.vm = vm;
13
- this.commandLine = commandLine;
14
- this.argv0 = argv0;
15
- this.id = id;
16
- this.dir = path.join(vm.root, 'compiles', "" + this.id);
17
- this.vmDir = path.join('/', 'compiles', "" + this.id);
18
- fs.mkdirpSync(this.dir);
19
- this.fd = fs.openSync(path.join(this.dir, 'sourcefile'), "w");
20
- this.cppSize = 0;
21
- this.startCompile = undefined;
22
- }
23
-
24
- sendCallback(error) {
25
- if (error) {
26
- console.error("Got send error for", this.vmDir, this.id, this.commandLine);
27
- this.vm.compileFinished({type: 'compileFinished', success: false, id: this.id, files: [], exitCode: -1, error: error.toString() });
28
- }
29
- }
30
-
31
- feed(data) {
32
- fs.writeSync(this.fd, data);
33
- this.cppSize += data.length;
34
- this.startCompile = Date.now();
35
- fs.close(this.fd);
36
- this.fd = undefined;
37
- this.vm.child.send({ type: "compile", commandLine: this.commandLine, argv0: this.argv0, id: this.id, dir: this.vmDir}, this.sendCallback.bind(this));
38
- }
39
-
40
- cancel() {
41
- this.vm.child.send({ type: "cancel", id: this.id}, this.sendCallback.bind(this));
42
- }
43
- };
44
-
45
- class VM extends EventEmitter
46
- {
47
- constructor(root, hash, option) {
48
- super();
49
- quitOnError = require('./quit-on-error')(option);
50
- this.root = root;
51
- this.hash = hash;
52
- this.compiles = {};
53
- this.destroying = false;
54
- this.keepCompiles = option("keep-compiles") || false;
55
-
56
- fs.remove(path.join(root, 'compiles'));
57
-
58
- let args = [ `--root=${root}`, `--hash=${hash}` ];
59
- let user = option("vm-user");
60
- if (user)
61
- args.push(`--user=${user}`);
62
- if (option("debug"))
63
- args.push("--debug");
64
-
65
- this.child = child_process.fork(path.join(__dirname, "VM_runtime.js"), args);
66
- let gotReady = false;
67
- this.child.on('message', msg => {
68
- // console.log("Got message", msg);
69
- switch (msg.type) {
70
- case 'ready':
71
- gotReady = true;
72
- this.emit('ready', { success: true });
73
- break;
74
- case 'error':
75
- console.error("Got error from runtime", this.hash, msg.message);
76
- break;
77
- case 'compileStdOut': {
78
- let compile = this.compiles[msg.id];
79
- if (compile)
80
- compile.emit('stdout', msg.data);
81
- break; }
82
- case 'compileStdErr': {
83
- let compile = this.compiles[msg.id];
84
- if (compile)
85
- compile.emit('stderr', msg.data);
86
- break; }
87
- case 'compileFinished':
88
- this.compileFinished(msg);
89
- break;
90
- }
91
- });
92
- this.child.on('error', err => {
93
- if (!gotReady) {
94
- this.emit('ready', { success: false, error: err });
95
- } else {
96
- console.error("Got error", err);
97
- }
98
- });
99
- this.child.on('exit', evt => {
100
- console.log("Child going down", evt, this.destroying);
101
- if (this.destroying)
102
- fs.remove(root);
103
- // ### need to handle the helper accidentally going down maybe?
104
- this.emit("exit");
105
- });
106
- }
107
-
108
- compileFinished(msg) {
109
- let compile = this.compiles[msg.id];
110
- if (!compile)
111
- return;
112
- if (msg.error)
113
- console.error("Got some error", msg.error);
114
- const now = Date.now();
115
- compile.emit('finished', {
116
- cppSize: compile.cppSize,
117
- compileDuration: (now - compile.startCompile),
118
- exitCode: msg.exitCode,
119
- success: msg.success,
120
- error: msg.error,
121
- sourceFile: msg.sourceFile,
122
- files: msg.files.map(file => {
123
- file.absolute = path.join(this.root, file.mapped ? file.mapped : file.path);
124
- delete file.mapped;
125
- return file;
126
- })
127
- });
128
-
129
- if (!this.keepCompiles)
130
- fs.remove(this.compiles[msg.id].dir);
131
- delete this.compiles[msg.id];
132
- }
133
-
134
- destroy() {
135
- this.destroying = true;
136
- this.child.send({type: 'destroy'}, err => {
137
- if (err) {
138
- console.error("Failed to send destroy message to child", this.hash, err);
139
- this.child.kill();
140
- }
141
- });
142
- }
143
-
144
- startCompile(commandLine, argv0, id) {
145
- let compile = new CompileJob(commandLine, argv0, id, this);
146
- this.compiles[compile.id] = compile;
147
- // console.log("startCompile " + compile.id);
148
- return compile;
149
- }
150
-
151
- setDebug(debug) {
152
- this.child.send({type: "setDebug", debug: debug});
153
- }
154
- };
155
-
156
- module.exports = VM;
@@ -1,171 +0,0 @@
1
- const path = require('path');
2
- const fs = require('fs');
3
- const os = require('os');
4
- const posix = require('posix');
5
- const Compile = require('./compile');
6
-
7
- const argv = require('minimist')(process.argv.slice(2));
8
-
9
- function send(message) {
10
- try {
11
- process.send(message);
12
- } catch (err) {
13
- console.error(`Couldn't send message ${message.type}. Going down`);
14
- process.exit();
15
- }
16
- }
17
-
18
- process.on('unhandledRejection', (reason, p) => {
19
- send({type: "error", message: `Unhandled rejection at: Promise ${p} reason: ${reason.stack}`});
20
- console.error('Unhandled rejection at: Promise', p, 'reason:', reason.stack);
21
- });
22
-
23
- process.on('uncaughtException', err => {
24
- send({type: "error", message: `Uncaught exception ${err.stack} ${err.toString()}`});
25
- console.error("Uncaught exception", err);
26
- });
27
-
28
- let pwd;
29
- if (argv.user) {
30
- try {
31
- pwd = posix.getpwnam(argv.user);
32
- } catch(err) {
33
- console.error("Couldn't find user", argv.user);
34
- throw err;
35
- }
36
-
37
- try {
38
- process.initgroups(argv.user, pwd.gid);
39
- } catch(err) {
40
- throw new Error('Changing groups failed: ' + err.message);
41
- }
42
- }
43
-
44
- try {
45
- console.log("Chrooting to", argv.root);
46
- posix.chroot(argv.root);
47
- } catch (err) {
48
- console.error('Changing root or user failed', err);
49
- process.exit(1);
50
- }
51
-
52
- if (pwd) {
53
- process.setgid(pwd.gid);
54
- process.setuid(pwd.uid);
55
- }
56
-
57
- process.on("error", error => {
58
- console.error(`Got process error ${error} ${JSON.stringify(argv)}. Going down`);
59
- process.exit();
60
- });
61
-
62
- let libDirs = [];
63
- const mac = os.type() === "Darwin";
64
-
65
- function isLibrary(file)
66
- {
67
- if (file == "ld.so.conf || file == ld.so.cache")
68
- return false;
69
- const suffix = path.extname(file);
70
- if (mac)
71
- return suffix == ".dylib";
72
-
73
- // console.log("got file", suffix, file);
74
- if (suffix == ".so") {
75
- return true;
76
- }
77
- return file.indexOf(".so.") != -1;
78
- }
79
-
80
- function findLibraries(dir)
81
- {
82
- const files = fs.readdirSync(dir);
83
- // console.log("findLibraries", dir, files.length);
84
- let found = false;
85
- files.forEach(file => {
86
- let stat;
87
- try {
88
- stat = fs.statSync(path.join(dir, file));
89
- } catch (err) {
90
- console.error("Got error", err);
91
- return;
92
- }
93
-
94
-
95
- if (stat.isDirectory()) {
96
- findLibraries(path.join(dir, file));
97
- } else if (!found && stat.isFile() && isLibrary(file)) {
98
- found = true;
99
- libDirs.push(dir);
100
- }
101
- });
102
- }
103
-
104
- findLibraries("/");
105
- if (argv.debug)
106
- console.log("Got lib directories", argv.root, libDirs);
107
- if (libDirs.length) {
108
- process.env[mac ? "DYLD_LIBRARY_PATH" : "LD_LIBRARY_PATH"] = libDirs.join(":");
109
- }
110
- setTimeout(() => { // hack
111
- try {
112
- send({type: "ready"});
113
- } catch (err) {
114
- console.error("Couldn't send ready. Going down");
115
- process.exit();
116
- }
117
- }, 1000);
118
-
119
- let compiles = {};
120
- let destroying = false;
121
-
122
- process.on('message', msg => {
123
- switch (msg.type) {
124
- case 'destroy':
125
- if (!compiles.length) {
126
- process.exit();
127
- } else {
128
- destroying = true;
129
- }
130
- break;
131
- case 'setDebug':
132
- if (msg.debug) {
133
- argv.debug = true;
134
- } else {
135
- delete argv["debug"];
136
- }
137
- console.log("set debug to", msg.debug, "for", argv.root);
138
- break;
139
- case 'cancel':
140
- let c = compiles[msg.id];
141
- if (c)
142
- c.kill();
143
- break;
144
- case 'compile':
145
- try {
146
- // console.log("compiling for );
147
- if (argv.debug) {
148
- console.log("Creating new compile", msg.commandLine, msg.argv0, msg.dir);
149
- }
150
- let compile = new Compile(msg.commandLine, msg.argv0, msg.dir, argv.debug);
151
- // console.log("running thing", msg.commandLine);
152
- compile.on('stdout', data => send({ type: 'compileStdOut', id: msg.id, data: data }));
153
- compile.on('stderr', data => send({ type: 'compileStdErr', id: msg.id, data: data }));
154
- compile.on('exit', event => {
155
- delete compiles[msg.id];
156
- if ("error" in event) {
157
- send({type: 'compileFinished', success: false, error: event.error, id: msg.id, files: event.files, exitCode: event.exitCode, sourceFile: event.sourceFile });
158
- } else {
159
- send({type: 'compileFinished', success: true, id: msg.id, files: event.files, exitCode: event.exitCode, sourceFile: event.sourceFile });
160
- }
161
- if (destroying && !compiles.length)
162
- process.exit();
163
- });
164
- compiles[msg.id] = compile;
165
- } catch (err) {
166
- delete compiles[msg.id];
167
- send({type: 'compileFinished', success: false, id: msg.id, files: [], exitCode: -1, error: err.toString() });
168
- }
169
- break;
170
- }
171
- });
package/builder/client.js DELETED
@@ -1,181 +0,0 @@
1
- const EventEmitter = require("events");
2
- const WebSocket = require("ws");
3
- const os = require('os');
4
- const path = require('path');
5
- const fs = require('fs');
6
-
7
- class Client extends EventEmitter {
8
- constructor(option, configVersion) {
9
- super();
10
-
11
- this.configVersion = configVersion;
12
- this.scheduler = option("scheduler", "ws://localhost:8097");
13
- if (this.scheduler.indexOf('://') == -1)
14
- this.scheduler = "ws://" + this.scheduler;
15
- if (!/:[0-9]+$/.exec(this.scheduler))
16
- this.scheduler += ":8097";
17
- this.serverPort = option.int("port", 8096);
18
- this.hostname = option("hostname");
19
- this.name = option("name");
20
- this.slots = option.int("slots", os.cpus().length);
21
- this.labels = option("labels");
22
- try {
23
- this.npmVersion = JSON.parse(fs.readFileSync(path.join(__dirname, "../package.json"))).version;
24
- } catch (err) {
25
- }
26
- console.log("this is our npm version", this.npmVersion);
27
- if (!this.name) {
28
- if (this.hostname) {
29
- this.name = this.hostname;
30
- } else {
31
- this.name = os.hostname();
32
- }
33
- }
34
- }
35
-
36
- connect(environments) {
37
- const url = `${this.scheduler}/builder`;
38
- console.log("connecting to", url);
39
-
40
- let remaining = 0;
41
- let system;
42
- switch (os.platform()) {
43
- case 'darwin': system = "Darwin"; break;
44
- case 'linux': system = "Linux"; break;
45
- default: console.error("Unknown platform", os.platform()); break;
46
- }
47
- switch (os.arch()) {
48
- case 'ia32': system += " i686"; break;
49
- case 'x64': system += " x86_64"; break;
50
- default: console.error("Unknown architecture", os.arch()); break;
51
- }
52
- let headers = {
53
- "x-fisk-port": this.serverPort,
54
- "x-fisk-environments": environments.join(";"),
55
- "x-fisk-config-version": this.configVersion,
56
- "x-fisk-builder-name": this.name,
57
- "x-fisk-system": system,
58
- "x-fisk-slots": this.slots,
59
- "x-fisk-npm-version": this.npmVersion
60
- };
61
-
62
- if (this.labels) {
63
- headers["x-fisk-builder-labels"] = this.labels;
64
- }
65
-
66
- if (this.hostname) {
67
- headers["x-fisk-builder-hostname"] = this.hostname;
68
- }
69
-
70
- this.ws = new WebSocket(url, { headers: headers });
71
- this.ws.on("open", () => {
72
- this.emit("connect");
73
- });
74
- this.ws.on("error", err => {
75
- console.error("client websocket error", err.message);
76
- });
77
- this.ws.on("upgrade", res => {
78
- this.emit("objectCache", res.headers["x-fisk-object-cache"] == "true");
79
- });
80
-
81
- this.ws.on("message", msg => {
82
- const error = msg => {
83
- this.ws.send(`{"error": "${msg}"}`);
84
- this.ws.close();
85
- this.emit("error", msg);
86
- };
87
-
88
- switch (typeof msg) {
89
- case "string":
90
- if (remaining) {
91
- // bad, client have to send all the data in a binary message before sending JSON
92
- error(`Got JSON message while ${remaining.bytes} bytes remained of a binary message`);
93
- return;
94
- }
95
- // assume JSON
96
- let json;
97
- try {
98
- json = JSON.parse(msg);
99
- } catch (e) {
100
- }
101
- if (json === undefined) {
102
- error("Unable to parse string message as JSON");
103
- return;
104
- }
105
- if (!json.type) {
106
- error("Bad message, no type");
107
- return;
108
- }
109
-
110
- console.log("got message from scheduler", json.type);
111
-
112
- if (json.bytes) {
113
- remaining = json.bytes;
114
- }
115
- this.emit(json.type, json);
116
- break;
117
- case "object":
118
- if (msg instanceof Buffer) {
119
- if (!msg.length) {
120
- // no data?
121
- error("No data in buffer");
122
- return;
123
- }
124
- if (!remaining) {
125
- error(`Unexpected binary message of length: ${msg.length}`);
126
- return;
127
- } else if (msg.length !== remaining) {
128
- // woops
129
- error(`length ${msg.length} !== ${remaining}`);
130
- return;
131
- }
132
- remaining = 0;
133
- this.emit("data", { data: msg });
134
- } else {
135
- error("Unexpected object");
136
- }
137
- break;
138
- }
139
- });
140
- this.ws.on("close", () => {
141
- if (remaining.bytes)
142
- this.emit("error", "Got close while reading a binary message");
143
- this.emit("close");
144
- if (this.ws)
145
- this.ws.removeAllListeners();
146
- this.ws = undefined;
147
- });
148
- }
149
-
150
- sendBinary(blob) {
151
- try {
152
- this.ws.send(blob);
153
- } catch (err) {
154
- this.emit("err", err.toString());
155
- }
156
- }
157
- send(type, msg) {
158
- if (!this.ws) {
159
- this.emit("error", "No connected websocket");
160
- return;
161
- }
162
- try {
163
- if (msg === undefined) {
164
- this.ws.send(JSON.stringify(type));
165
- } else {
166
- let tosend;
167
- if (typeof msg === "object") {
168
- tosend = msg;
169
- tosend.type = type;
170
- } else {
171
- tosend = { type: type, message: msg };
172
- }
173
- this.ws.send(JSON.stringify(tosend));
174
- }
175
- } catch (err) {
176
- this.emit("err", err.toString());
177
- }
178
- }
179
- }
180
-
181
- module.exports = Client;