@gitpod/gitpod-protocol 0.1.5-sefftinge-create-feature-flag-for-4354.0 → 0.1.5-server-vscode-oauth2.11

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.
Files changed (223) hide show
  1. package/data/gitpod-schema.json +4 -22
  2. package/lib/accounting-protocol.d.ts +3 -5
  3. package/lib/accounting-protocol.d.ts.map +1 -1
  4. package/lib/accounting-protocol.js +6 -11
  5. package/lib/accounting-protocol.js.map +1 -1
  6. package/lib/admin-protocol.d.ts +9 -4
  7. package/lib/admin-protocol.d.ts.map +1 -1
  8. package/lib/admin-protocol.js +2 -13
  9. package/lib/admin-protocol.js.map +1 -1
  10. package/lib/analytics.d.ts +44 -0
  11. package/lib/analytics.d.ts.map +1 -0
  12. package/lib/{util/without.js → analytics.js} +4 -2
  13. package/lib/analytics.js.map +1 -0
  14. package/lib/context-url.d.ts +18 -0
  15. package/lib/context-url.d.ts.map +1 -0
  16. package/lib/context-url.js +49 -0
  17. package/lib/context-url.js.map +1 -0
  18. package/lib/{util/context-url.spec.d.ts → context-url.spec.d.ts} +2 -0
  19. package/lib/context-url.spec.d.ts.map +1 -0
  20. package/lib/context-url.spec.js +73 -0
  21. package/lib/context-url.spec.js.map +1 -0
  22. package/lib/email-protocol.d.ts +1 -2
  23. package/lib/email-protocol.d.ts.map +1 -1
  24. package/lib/email-protocol.js +3 -3
  25. package/lib/email-protocol.js.map +1 -1
  26. package/lib/encryption/container-module.js +4 -4
  27. package/lib/encryption/container-module.js.map +1 -1
  28. package/lib/encryption/encryption-engine.js +19 -20
  29. package/lib/encryption/encryption-engine.js.map +1 -1
  30. package/lib/encryption/encryption-engine.spec.js +29 -36
  31. package/lib/encryption/encryption-engine.spec.js.map +1 -1
  32. package/lib/encryption/encryption-service.js +29 -43
  33. package/lib/encryption/encryption-service.js.map +1 -1
  34. package/lib/encryption/key-provider.js +25 -30
  35. package/lib/encryption/key-provider.js.map +1 -1
  36. package/lib/env.d.ts +1 -2
  37. package/lib/env.d.ts.map +1 -1
  38. package/lib/env.js +20 -21
  39. package/lib/env.js.map +1 -1
  40. package/lib/gitpod-file-parser.js +25 -41
  41. package/lib/gitpod-file-parser.js.map +1 -1
  42. package/lib/gitpod-file-parser.spec.js +116 -116
  43. package/lib/gitpod-file-parser.spec.js.map +1 -1
  44. package/lib/gitpod-service.d.ts +74 -5
  45. package/lib/gitpod-service.d.ts.map +1 -1
  46. package/lib/gitpod-service.js +149 -294
  47. package/lib/gitpod-service.js.map +1 -1
  48. package/lib/headless-workspace-log.d.ts +8 -11
  49. package/lib/headless-workspace-log.d.ts.map +1 -1
  50. package/lib/headless-workspace-log.js +4 -7
  51. package/lib/headless-workspace-log.js.map +1 -1
  52. package/lib/index.d.ts +2 -0
  53. package/lib/index.d.ts.map +1 -1
  54. package/lib/index.js +2 -0
  55. package/lib/index.js.map +1 -1
  56. package/lib/messaging/browser/connection.d.ts +3 -3
  57. package/lib/messaging/browser/connection.d.ts.map +1 -1
  58. package/lib/messaging/browser/connection.js +172 -35
  59. package/lib/messaging/browser/connection.js.map +1 -1
  60. package/lib/messaging/browser/window-connection.js +34 -54
  61. package/lib/messaging/browser/window-connection.js.map +1 -1
  62. package/lib/messaging/client-call-metrics.d.ts +35 -0
  63. package/lib/messaging/client-call-metrics.d.ts.map +1 -0
  64. package/lib/messaging/client-call-metrics.js +83 -0
  65. package/lib/messaging/client-call-metrics.js.map +1 -0
  66. package/lib/messaging/connection-error-handler.js +11 -23
  67. package/lib/messaging/connection-error-handler.js.map +1 -1
  68. package/lib/messaging/error.d.ts +1 -0
  69. package/lib/messaging/error.d.ts.map +1 -1
  70. package/lib/messaging/error.js +2 -0
  71. package/lib/messaging/error.js.map +1 -1
  72. package/lib/messaging/handler.d.ts +10 -0
  73. package/lib/messaging/handler.d.ts.map +1 -1
  74. package/lib/messaging/node/connection.js +21 -21
  75. package/lib/messaging/node/connection.js.map +1 -1
  76. package/lib/messaging/proxy-factory.d.ts +2 -0
  77. package/lib/messaging/proxy-factory.d.ts.map +1 -1
  78. package/lib/messaging/proxy-factory.js +74 -159
  79. package/lib/messaging/proxy-factory.js.map +1 -1
  80. package/lib/permission.d.ts +1 -2
  81. package/lib/permission.d.ts.map +1 -1
  82. package/lib/permission.js +12 -13
  83. package/lib/permission.js.map +1 -1
  84. package/lib/plans.js +38 -57
  85. package/lib/plans.js.map +1 -1
  86. package/lib/protocol.d.ts +52 -22
  87. package/lib/protocol.d.ts.map +1 -1
  88. package/lib/protocol.js +68 -115
  89. package/lib/protocol.js.map +1 -1
  90. package/lib/team-subscription-protocol.d.ts +3 -3
  91. package/lib/team-subscription-protocol.d.ts.map +1 -1
  92. package/lib/team-subscription-protocol.js +13 -10
  93. package/lib/team-subscription-protocol.js.map +1 -1
  94. package/lib/teams-projects-protocol.d.ts +102 -0
  95. package/lib/teams-projects-protocol.d.ts.map +1 -0
  96. package/lib/teams-projects-protocol.js +23 -0
  97. package/lib/teams-projects-protocol.js.map +1 -0
  98. package/lib/util/analytics.d.ts +1 -26
  99. package/lib/util/analytics.d.ts.map +1 -1
  100. package/lib/util/analytics.js +36 -28
  101. package/lib/util/analytics.js.map +1 -1
  102. package/lib/util/async-iterator.js +55 -133
  103. package/lib/util/async-iterator.js.map +1 -1
  104. package/lib/util/cancelable.js +17 -59
  105. package/lib/util/cancelable.js.map +1 -1
  106. package/lib/util/date-time.js +8 -8
  107. package/lib/util/date-time.js.map +1 -1
  108. package/lib/util/deferred.js +10 -12
  109. package/lib/util/deferred.js.map +1 -1
  110. package/lib/util/disposable.js +26 -39
  111. package/lib/util/disposable.js.map +1 -1
  112. package/lib/util/event.js +58 -74
  113. package/lib/util/event.js.map +1 -1
  114. package/lib/util/garbage-collected-cache.js +22 -46
  115. package/lib/util/garbage-collected-cache.js.map +1 -1
  116. package/lib/util/generate-workspace-id.d.ts.map +1 -1
  117. package/lib/util/generate-workspace-id.js +12 -67
  118. package/lib/util/generate-workspace-id.js.map +1 -1
  119. package/lib/util/generate-workspace-id.spec.js +34 -79
  120. package/lib/util/generate-workspace-id.spec.js.map +1 -1
  121. package/lib/util/gitpod-cookie.d.ts +20 -0
  122. package/lib/util/gitpod-cookie.d.ts.map +1 -0
  123. package/lib/util/gitpod-cookie.js +44 -0
  124. package/lib/util/gitpod-cookie.js.map +1 -0
  125. package/lib/util/gitpod-host-url.js +93 -103
  126. package/lib/util/gitpod-host-url.js.map +1 -1
  127. package/lib/util/gitpod-host-url.spec.d.ts +5 -0
  128. package/lib/util/gitpod-host-url.spec.d.ts.map +1 -1
  129. package/lib/util/gitpod-host-url.spec.js +92 -70
  130. package/lib/util/gitpod-host-url.spec.js.map +1 -1
  131. package/lib/util/grpc.d.ts +15 -0
  132. package/lib/util/grpc.d.ts.map +1 -0
  133. package/lib/util/grpc.js +18 -0
  134. package/lib/util/grpc.js.map +1 -0
  135. package/lib/util/logging.d.ts +17 -1
  136. package/lib/util/logging.d.ts.map +1 -1
  137. package/lib/util/logging.js +107 -110
  138. package/lib/util/logging.js.map +1 -1
  139. package/lib/util/make-link.js +2 -2
  140. package/lib/util/make-link.js.map +1 -1
  141. package/lib/util/parse-workspace-id.d.ts +10 -0
  142. package/lib/util/parse-workspace-id.d.ts.map +1 -1
  143. package/lib/util/parse-workspace-id.js +31 -7
  144. package/lib/util/parse-workspace-id.js.map +1 -1
  145. package/lib/util/parse-workspace-id.spec.d.ts +4 -0
  146. package/lib/util/parse-workspace-id.spec.d.ts.map +1 -1
  147. package/lib/util/parse-workspace-id.spec.js +123 -84
  148. package/lib/util/parse-workspace-id.spec.js.map +1 -1
  149. package/lib/util/queue.js +16 -55
  150. package/lib/util/queue.js.map +1 -1
  151. package/lib/util/queue.spec.js +144 -288
  152. package/lib/util/queue.spec.js.map +1 -1
  153. package/lib/util/repeater.js +35 -88
  154. package/lib/util/repeater.js.map +1 -1
  155. package/lib/util/safe-promise.js +9 -12
  156. package/lib/util/safe-promise.js.map +1 -1
  157. package/lib/util/semaphore.js +15 -46
  158. package/lib/util/semaphore.js.map +1 -1
  159. package/lib/util/skip-if.js +6 -6
  160. package/lib/util/skip-if.js.map +1 -1
  161. package/lib/util/timeutil.js +16 -16
  162. package/lib/util/timeutil.js.map +1 -1
  163. package/lib/util/timeutil.spec.js +21 -24
  164. package/lib/util/timeutil.spec.js.map +1 -1
  165. package/lib/util/tracing.js +43 -47
  166. package/lib/util/tracing.js.map +1 -1
  167. package/lib/util/workspace-port-authentication.js +2 -2
  168. package/lib/util/workspace-port-authentication.js.map +1 -1
  169. package/lib/workspace-cluster.d.ts +12 -3
  170. package/lib/workspace-cluster.d.ts.map +1 -1
  171. package/lib/workspace-cluster.js +3 -3
  172. package/lib/workspace-cluster.js.map +1 -1
  173. package/lib/workspace-instance.d.ts +3 -0
  174. package/lib/workspace-instance.d.ts.map +1 -1
  175. package/lib/wsready.js +1 -1
  176. package/lib/wsready.js.map +1 -1
  177. package/package.json +11 -6
  178. package/pkg-yarn.lock +7 -4
  179. package/src/accounting-protocol.ts +3 -7
  180. package/src/admin-protocol.ts +10 -5
  181. package/src/analytics.ts +52 -0
  182. package/src/context-url.spec.ts +39 -0
  183. package/src/context-url.ts +51 -0
  184. package/src/email-protocol.ts +1 -2
  185. package/src/env.ts +10 -10
  186. package/src/gitpod-service.ts +90 -12
  187. package/src/headless-workspace-log.ts +7 -11
  188. package/src/index.ts +2 -0
  189. package/src/messaging/browser/connection.ts +176 -10
  190. package/src/messaging/client-call-metrics.ts +97 -0
  191. package/src/messaging/error.ts +3 -0
  192. package/src/messaging/handler.ts +12 -0
  193. package/src/messaging/node/connection.ts +2 -2
  194. package/src/messaging/proxy-factory.ts +13 -5
  195. package/src/permission.ts +0 -1
  196. package/src/protocol.ts +73 -28
  197. package/src/team-subscription-protocol.ts +5 -3
  198. package/src/teams-projects-protocol.ts +131 -0
  199. package/src/util/analytics.ts +17 -30
  200. package/src/util/generate-workspace-id.ts +1 -0
  201. package/src/util/gitpod-cookie.ts +39 -0
  202. package/src/util/gitpod-host-url.spec.ts +20 -0
  203. package/src/util/gitpod-host-url.ts +1 -1
  204. package/src/util/grpc.ts +15 -0
  205. package/src/util/logging.ts +70 -6
  206. package/src/util/parse-workspace-id.spec.ts +21 -1
  207. package/src/util/parse-workspace-id.ts +32 -6
  208. package/src/workspace-cluster.ts +9 -3
  209. package/src/workspace-instance.ts +19 -7
  210. package/src/wsready.ts +1 -1
  211. package/lib/util/context-url.d.ts +0 -13
  212. package/lib/util/context-url.d.ts.map +0 -1
  213. package/lib/util/context-url.js +0 -26
  214. package/lib/util/context-url.js.map +0 -1
  215. package/lib/util/context-url.spec.d.ts.map +0 -1
  216. package/lib/util/context-url.spec.js +0 -52
  217. package/lib/util/context-url.spec.js.map +0 -1
  218. package/lib/util/without.d.ts +0 -7
  219. package/lib/util/without.d.ts.map +0 -1
  220. package/lib/util/without.js.map +0 -1
  221. package/src/util/context-url.spec.ts +0 -25
  222. package/src/util/context-url.ts +0 -23
  223. package/src/util/without.ts +0 -8
@@ -5,10 +5,13 @@
5
5
  * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
6
  */
7
7
 
8
- import { listen as doListen, Logger, ConsoleLogger } from "vscode-ws-jsonrpc";
8
+ import { Logger, ConsoleLogger, toSocket, IWebSocket } from "vscode-ws-jsonrpc";
9
+ import { createMessageConnection } from "vscode-jsonrpc";
10
+ import { AbstractMessageWriter } from "vscode-jsonrpc/lib/messageWriter";
11
+ import { AbstractMessageReader } from "vscode-jsonrpc/lib/messageReader";
9
12
  import { JsonRpcProxyFactory, JsonRpcProxy } from "../proxy-factory";
10
- import { ConnectionHandler } from "../handler";
11
- import ReconnectingWebSocket from 'reconnecting-websocket';
13
+ import { ConnectionEventHandler, ConnectionHandler } from "../handler";
14
+ import ReconnectingWebSocket, { Event } from 'reconnecting-websocket';
12
15
 
13
16
  export interface WebSocketOptions {
14
17
  onerror?: (event: Event) => void;
@@ -29,7 +32,10 @@ export class WebSocketConnectionProvider {
29
32
  const startListening = (path: string) => {
30
33
  const socket = this.listen({
31
34
  path,
32
- onConnection: c => factory.listen(c)
35
+ onConnection: c => factory.listen(c),
36
+ }, {
37
+ onTransportDidClose: () => factory.fireConnectionClosed(),
38
+ onTransportDidOpen: () => factory.fireConnectionOpened(),
33
39
  },
34
40
  options
35
41
  );
@@ -49,7 +55,7 @@ export class WebSocketConnectionProvider {
49
55
  /**
50
56
  * Install a connection handler for the given path.
51
57
  */
52
- listen(handler: ConnectionHandler, options?: WebSocketOptions): WebSocket {
58
+ listen(handler: ConnectionHandler, eventHandler: ConnectionEventHandler, options?: WebSocketOptions): WebSocket {
53
59
  const url = handler.path;
54
60
  const webSocket = this.createWebSocket(url);
55
61
 
@@ -64,11 +70,12 @@ export class WebSocketConnectionProvider {
64
70
  logger.error(JSON.stringify(error));
65
71
  });
66
72
  }
67
- doListen({
68
- webSocket,
69
- onConnection: connection => handler.onConnection(connection),
70
- logger
71
- });
73
+ doListen(
74
+ webSocket as any as ReconnectingWebSocket,
75
+ handler,
76
+ eventHandler,
77
+ logger,
78
+ );
72
79
  return webSocket;
73
80
  }
74
81
 
@@ -91,3 +98,162 @@ export class WebSocketConnectionProvider {
91
98
  }
92
99
 
93
100
  }
101
+
102
+ // The following was extracted from vscode-ws-jsonrpc to make these changes:
103
+ // - switch from WebSocket to ReconnectingWebSocket
104
+ // - webSocket.onopen: making sure it's only ever called once so we're re-using MessageConnection
105
+ // - WebSocketMessageWriter: buffer and re-try messages instead of throwing an error immidiately
106
+ // - WebSocketMessageReader: don't close MessageConnection on 'socket.onclose'
107
+ function doListen(resocket: ReconnectingWebSocket, handler: ConnectionHandler, eventHandler: ConnectionEventHandler, logger: Logger) {
108
+ resocket.addEventListener("close", () => eventHandler.onTransportDidClose());
109
+
110
+ let alreadyOpened = false;
111
+ resocket.onopen = () => {
112
+ // trigerr "open" every time we re-open the underlying websocket
113
+ eventHandler.onTransportDidOpen();
114
+
115
+ // make sure we're only ever creating one MessageConnection, irregardless of how many times we have to re-open the underlying (reconnecting) websocket
116
+ if (alreadyOpened) {
117
+ return;
118
+ }
119
+ alreadyOpened = true;
120
+
121
+ const connection = createWebSocketConnection(resocket, logger);
122
+ handler.onConnection(connection);
123
+ };
124
+ }
125
+
126
+ function createWebSocketConnection(resocket: ReconnectingWebSocket, logger: Logger) {
127
+ const socket = toSocket(resocket as any);
128
+ const messageReader = new NonClosingWebSocketMessageReader(socket);
129
+ const messageWriter = new BufferingWebSocketMessageWriter(resocket, logger);
130
+ const connection = createMessageConnection(messageReader, messageWriter, logger);
131
+ connection.onClose(() => connection.dispose());
132
+ return connection;
133
+ }
134
+
135
+ /**
136
+ * This takes vscode-ws-jsonrpc/lib/socket/writer/WebSocketMessageWriter and adds a buffer
137
+ */
138
+ class BufferingWebSocketMessageWriter extends AbstractMessageWriter {
139
+ protected readonly socket: ReconnectingWebSocket;
140
+ protected readonly logger: Logger;
141
+ protected errorCount: number = 0;
142
+
143
+ protected buffer: any[] = [];
144
+
145
+ constructor(socket: ReconnectingWebSocket, logger: Logger) {
146
+ super();
147
+ this.socket = socket;
148
+ this.logger = logger;
149
+
150
+ socket.addEventListener("open", (event: Event) => this.flushBuffer());
151
+ }
152
+
153
+ write(msg: any) {
154
+ if (this.socket.readyState !== ReconnectingWebSocket.OPEN) {
155
+ this.bufferMsg(msg);
156
+ return;
157
+ }
158
+
159
+ try {
160
+ const content = JSON.stringify(msg);
161
+ this.socket.send(content);
162
+ } catch (e) {
163
+ this.errorCount++;
164
+ this.fireError(e, msg, this.errorCount);
165
+
166
+ this.bufferMsg(msg);
167
+ }
168
+ }
169
+
170
+ protected flushBuffer() {
171
+ if (this.buffer.length === 0) {
172
+ return
173
+ }
174
+
175
+ const buffer = [...this.buffer];
176
+ this.buffer = [];
177
+ for (const msg of buffer) {
178
+ this.write(msg);
179
+ }
180
+ //this.logger.info(`flushed buffer (${this.buffer.length})`)
181
+ }
182
+
183
+ protected bufferMsg(msg: any) {
184
+ this.buffer.push(msg);
185
+ //this.logger.info(`buffered message (${this.buffer.length})`);
186
+ }
187
+ }
188
+
189
+
190
+ /**
191
+ * This takes vscode-ws-jsonrpc/lib/socket/reader/WebSocketMessageReader and removes the "onClose -> fireClose" connection
192
+ */
193
+ class NonClosingWebSocketMessageReader extends AbstractMessageReader {
194
+ protected readonly socket: IWebSocket;
195
+ protected readonly events: any[] = [];
196
+ protected state: 'initial' | 'listening' | 'closed' = 'initial';
197
+ protected callback: (message: any) => void = () => {};
198
+
199
+ constructor(socket: IWebSocket) {
200
+ super();
201
+ this.socket = socket;
202
+ this.socket.onMessage(message => this.readMessage(message));
203
+ this.socket.onError(error => this.fireError(error));
204
+ this.socket.onClose((code, reason) => {
205
+ if (code !== 1000) {
206
+ const error = {
207
+ name: '' + code,
208
+ message: `Error during socket reconnect: code = ${code}, reason = ${reason}`
209
+ };
210
+ this.fireError(error);
211
+ }
212
+ // this.fireClose(); // <-- reason for this class to be copied over
213
+ });
214
+ }
215
+ listen(callback: (message: any) => void) {
216
+ if (this.state === 'initial') {
217
+ this.state = 'listening';
218
+ this.callback = callback;
219
+ while (this.events.length !== 0) {
220
+ const event = this.events.pop();
221
+ if (event.message) {
222
+ this.readMessage(event.message);
223
+ }
224
+ else if (event.error) {
225
+ this.fireError(event.error);
226
+ }
227
+ else {
228
+ this.fireClose();
229
+ }
230
+ }
231
+ }
232
+ }
233
+ readMessage(message: any) {
234
+ if (this.state === 'initial') {
235
+ this.events.splice(0, 0, { message });
236
+ }
237
+ else if (this.state === 'listening') {
238
+ const data = JSON.parse(message);
239
+ this.callback(data);
240
+ }
241
+ }
242
+ fireError(error: any) {
243
+ if (this.state === 'initial') {
244
+ this.events.splice(0, 0, { error });
245
+ }
246
+ else if (this.state === 'listening') {
247
+ super.fireError(error);
248
+ }
249
+ }
250
+ fireClose() {
251
+ if (this.state === 'initial') {
252
+ this.events.splice(0, 0, {});
253
+ }
254
+ else if (this.state === 'listening') {
255
+ super.fireClose();
256
+ }
257
+ this.state = 'closed';
258
+ }
259
+ }
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Copyright (c) 2021 Gitpod GmbH. All rights reserved.
3
+ * Licensed under the GNU Affero General Public License (AGPL).
4
+ * See License-AGPL.txt in the project root for license information.
5
+ */
6
+
7
+ import { injectable } from 'inversify';
8
+ import * as prometheusClient from 'prom-client';
9
+
10
+ type GrpcMethodType = 'unary' | 'client_stream' | 'server_stream' | 'bidi_stream';
11
+ export interface IGrpcCallMetricsLabels {
12
+ service: string,
13
+ method: string,
14
+ type: GrpcMethodType,
15
+ }
16
+
17
+ export interface IGrpcCallMetricsLabelsWithCode extends IGrpcCallMetricsLabels {
18
+ code: string
19
+ }
20
+
21
+ export const IClientCallMetrics = Symbol("IClientCallMetrics");
22
+
23
+ export interface IClientCallMetrics {
24
+ started(labels: IGrpcCallMetricsLabels) : void;
25
+ sent(labels: IGrpcCallMetricsLabels) : void;
26
+ received(labels: IGrpcCallMetricsLabels) : void;
27
+ handled(labels: IGrpcCallMetricsLabelsWithCode) : void;
28
+ }
29
+
30
+ @injectable()
31
+ export class PrometheusClientCallMetrics implements IClientCallMetrics {
32
+
33
+ readonly startedCounter: prometheusClient.Counter<string>;
34
+ readonly sentCounter: prometheusClient.Counter<string>;
35
+ readonly receivedCounter: prometheusClient.Counter<string>;
36
+ readonly handledCounter: prometheusClient.Counter<string>;
37
+
38
+ constructor() {
39
+ this.startedCounter = new prometheusClient.Counter({
40
+ name: 'grpc_client_started_total',
41
+ help: 'Total number of RPCs started on the client.',
42
+ labelNames: ['grpc_service', 'grpc_method', 'grpc_type'],
43
+ registers: [prometheusClient.register]
44
+ });
45
+ this.sentCounter = new prometheusClient.Counter({
46
+ name: 'grpc_client_msg_sent_total',
47
+ help: ' Total number of gRPC stream messages sent by the client.',
48
+ labelNames: ['grpc_service', 'grpc_method', 'grpc_type'],
49
+ registers: [prometheusClient.register]
50
+ });
51
+ this.receivedCounter = new prometheusClient.Counter({
52
+ name: 'grpc_client_msg_received_total',
53
+ help: 'Total number of RPC stream messages received by the client.',
54
+ labelNames: ['grpc_service', 'grpc_method', 'grpc_type'],
55
+ registers: [prometheusClient.register]
56
+ });
57
+ this.handledCounter = new prometheusClient.Counter({
58
+ name: 'grpc_client_handled_total',
59
+ help: 'Total number of RPCs completed by the client, regardless of success or failure.',
60
+ labelNames: ['grpc_service', 'grpc_method', 'grpc_type', 'grpc_code'],
61
+ registers: [prometheusClient.register]
62
+ });
63
+ }
64
+
65
+ started(labels: IGrpcCallMetricsLabels): void {
66
+ this.startedCounter.inc({
67
+ grpc_service: labels.service,
68
+ grpc_method: labels.method,
69
+ grpc_type: labels.type
70
+ });
71
+ }
72
+
73
+ sent(labels: IGrpcCallMetricsLabels): void {
74
+ this.sentCounter.inc({
75
+ grpc_service: labels.service,
76
+ grpc_method: labels.method,
77
+ grpc_type: labels.type
78
+ });
79
+ }
80
+
81
+ received(labels: IGrpcCallMetricsLabels): void {
82
+ this.receivedCounter.inc({
83
+ grpc_service: labels.service,
84
+ grpc_method: labels.method,
85
+ grpc_type: labels.type
86
+ });
87
+ }
88
+
89
+ handled(labels: IGrpcCallMetricsLabelsWithCode): void {
90
+ this.handledCounter.inc({
91
+ grpc_service: labels.service,
92
+ grpc_method: labels.method,
93
+ grpc_type: labels.type,
94
+ grpc_code: labels.code
95
+ });
96
+ }
97
+ }
@@ -34,6 +34,9 @@ export namespace ErrorCodes {
34
34
  // 460 Context Parse Error (custom status code)
35
35
  export const CONTEXT_PARSE_ERROR = 460;
36
36
 
37
+ // 461 Invalid gitpod yml
38
+ export const INVALID_GITPOD_YML = 461;
39
+
37
40
  // 450 Payment error
38
41
  export const PAYMENT_ERROR = 450;
39
42
 
@@ -13,3 +13,15 @@ export interface ConnectionHandler {
13
13
  readonly path: string;
14
14
  onConnection(connection: MessageConnection, session?: object): void;
15
15
  }
16
+
17
+ export interface ConnectionEventHandler {
18
+ /**
19
+ * Called when the transport underpinning the connection got closed
20
+ */
21
+ onTransportDidClose(): void;
22
+
23
+ /**
24
+ * Called when the transport underpinning the connection is (re-)opened
25
+ */
26
+ onTransportDidOpen(): void;
27
+ }
@@ -65,13 +65,13 @@ export function toIWebSocket(webSocket: ws) {
65
65
  send: content => {
66
66
  if (webSocket.readyState !== ws.OPEN) {
67
67
  if (sendsAfterOpen++ > 3) {
68
- log.error(`Repeated try to send on closed web socket (readyState was ${webSocket.readyState})`, { ws });
68
+ //log.debug(`Repeated try to send on closed web socket (readyState was ${webSocket.readyState})`, { ws });
69
69
  }
70
70
  return;
71
71
  }
72
72
  webSocket.send(content, err => {
73
73
  if (err) {
74
- log.error('Error in ws.send()', err, { ws });
74
+ log.error('error in ws.send()', err, { ws });
75
75
  }
76
76
  })
77
77
  },
@@ -105,13 +105,19 @@ export class JsonRpcProxyFactory<T extends object> implements ProxyHandler<T> {
105
105
  this.connectionPromiseResolve = resolve
106
106
  );
107
107
  this.connectionPromise.then(connection => {
108
- connection.onClose(() =>
109
- this.onDidCloseConnectionEmitter.fire(undefined)
110
- );
111
- this.onDidOpenConnectionEmitter.fire(undefined);
108
+ connection.onClose(() => this.fireConnectionClosed());
109
+ this.fireConnectionOpened();
112
110
  });
113
111
  }
114
112
 
113
+ fireConnectionClosed() {
114
+ this.onDidCloseConnectionEmitter.fire(undefined)
115
+ }
116
+
117
+ fireConnectionOpened() {
118
+ this.onDidOpenConnectionEmitter.fire(undefined);
119
+ }
120
+
115
121
  /**
116
122
  * Connect a MessageConnection to the factory.
117
123
  *
@@ -158,7 +164,9 @@ export class JsonRpcProxyFactory<T extends object> implements ProxyHandler<T> {
158
164
  * methods calls.
159
165
  */
160
166
  protected onNotification(method: string, ...args: any[]): void {
161
- this.target[method](...args);
167
+ if (this.target[method]) {
168
+ this.target[method](...args);
169
+ }
162
170
  }
163
171
 
164
172
  /**
package/src/permission.ts CHANGED
@@ -16,7 +16,6 @@ export const Permissions = {
16
16
  "admin-api": undefined,
17
17
  "ide-settings": undefined,
18
18
  "new-workspace-cluster": undefined,
19
- "teams-and-projects": undefined,
20
19
  };
21
20
  export type PermissionName = keyof (typeof Permissions);
22
21
  export const Roles = {"devops": undefined, "viewer": undefined, "admin": undefined };
package/src/protocol.ts CHANGED
@@ -6,6 +6,7 @@
6
6
 
7
7
  import { WorkspaceInstance, PortVisibility } from "./workspace-instance";
8
8
  import { RoleOrPermission } from "./permission";
9
+ import { Project } from "./teams-projects-protocol";
9
10
 
10
11
  export interface UserInfo {
11
12
  name?: string
@@ -27,8 +28,6 @@ export interface User {
27
28
 
28
29
  identities: Identity[]
29
30
 
30
- allowsMarketingCommunication: boolean;
31
-
32
31
  /**
33
32
  * Whether the user has been blocked to use our service, because of TOS violation for example.
34
33
  * Optional for backwards compatibility.
@@ -103,10 +102,14 @@ export interface AdditionalUserData {
103
102
  // key is the name of the OAuth client i.e. local app, string the iso date when it was approved
104
103
  // TODO(rl): provide a management UX to allow rescinding of approval
105
104
  oauthClientsApproved?: { [key: string]: string }
105
+ // to remember GH Orgs the user installed/updated the GH App for
106
+ knownGitHubOrgs?: string[];
106
107
  }
107
108
 
108
109
  export interface EmailNotificationSettings {
109
- disallowTransactionalEmails?: boolean;
110
+ allowsChangelogMail?: boolean;
111
+ allowsDevXMail?: boolean;
112
+ allowsOnboardingMail?: boolean;
110
113
  }
111
114
 
112
115
  export type IDESettings = {
@@ -392,6 +395,7 @@ export interface Workspace {
392
395
  contextURL: string;
393
396
  description: string;
394
397
  ownerId: string;
398
+ projectId?: string;
395
399
  context: WorkspaceContext;
396
400
  config: WorkspaceConfig;
397
401
 
@@ -559,11 +563,13 @@ export interface WorkspaceConfig {
559
563
  * Where the config object originates from.
560
564
  *
561
565
  * repo - from the repository
566
+ * project-db - from the "Project" stored in the database
562
567
  * definitly-gp - from github.com/gitpod-io/definitely-gp
563
568
  * derived - computed based on analyzing the repository
569
+ * additional-content - config comes from additional content, usually provided through the project's configuration
564
570
  * default - our static catch-all default config
565
571
  */
566
- _origin?: 'repo' | 'definitely-gp' | 'derived' | 'default';
572
+ _origin?: 'repo' | 'project-db' | 'definitely-gp' | 'derived' | 'additional-content' | 'default';
567
573
 
568
574
  /**
569
575
  * Set of automatically infered feature flags. That's not something the user can set, but
@@ -593,16 +599,13 @@ export namespace GithubAppPrebuildConfig {
593
599
 
594
600
  export type WorkspaceImageSource = WorkspaceImageSourceDocker | WorkspaceImageSourceReference;
595
601
  export interface WorkspaceImageSourceDocker {
596
- // TODO: clean this up. We should have the commit and an ImageSource in here, not duplicate the whole thing again.
597
- // We have a ton of those objects in the database, thus cleaning this up means lengthy DB migrations. Yuck.
598
- dockerFileHash: string
599
- dockerFileSource: Commit
600
602
  dockerFilePath: string
603
+ dockerFileHash: string
604
+ dockerFileSource?: Commit
601
605
  }
602
606
  export namespace WorkspaceImageSourceDocker {
603
607
  export function is(obj: object): obj is WorkspaceImageSourceDocker {
604
608
  return 'dockerFileHash' in obj
605
- && 'dockerFileSource' in obj
606
609
  && 'dockerFilePath' in obj;
607
610
  }
608
611
  }
@@ -631,6 +634,8 @@ export type PrebuiltWorkspaceState
631
634
  export interface PrebuiltWorkspace {
632
635
  id: string;
633
636
  cloneURL: string;
637
+ branch?: string;
638
+ projectId?: string;
634
639
  commit: string;
635
640
  buildWorkspaceId: string;
636
641
  creationTime: string;
@@ -700,7 +705,7 @@ export interface TaskConfig {
700
705
  init?: string;
701
706
  prebuild?: string;
702
707
  command?: string;
703
- env?: { [env: string]: string };
708
+ env?: { [env: string]: any };
704
709
  openIn?: 'bottom' | 'main' | 'left' | 'right';
705
710
  openMode?: 'split-top' | 'split-left' | 'split-right' | 'split-bottom' | 'tab-before' | 'tab-after';
706
711
  }
@@ -800,6 +805,29 @@ export namespace WithPrebuild {
800
805
  }
801
806
  }
802
807
 
808
+ /**
809
+ * WithDefaultConfig contexts disable the download of the gitpod.yml from the repository
810
+ * and fall back to the built-in configuration.
811
+ */
812
+ export interface WithDefaultConfig {
813
+ withDefaultConfig: true;
814
+ }
815
+
816
+ export namespace WithDefaultConfig {
817
+ export function is(context: any): context is WithDefaultConfig {
818
+ return context
819
+ && 'withDefaultConfig' in context
820
+ && context.withDefaultConfig;
821
+ }
822
+
823
+ export function mark(ctx: WorkspaceContext): WorkspaceContext & WithDefaultConfig {
824
+ return {
825
+ ...ctx,
826
+ withDefaultConfig: true
827
+ }
828
+ }
829
+ }
830
+
803
831
  export interface SnapshotContext extends WorkspaceContext, WithSnapshot {
804
832
  snapshotId: string;
805
833
  }
@@ -815,6 +843,8 @@ export namespace SnapshotContext {
815
843
  export interface StartPrebuildContext extends WorkspaceContext {
816
844
  actual: WorkspaceContext;
817
845
  commitHistory?: string[];
846
+ project?: Project;
847
+ branch?: string;
818
848
  }
819
849
 
820
850
  export namespace StartPrebuildContext {
@@ -884,6 +914,25 @@ export interface Commit {
884
914
  refType?: RefType
885
915
  }
886
916
 
917
+ export interface AdditionalContentContext extends WorkspaceContext {
918
+
919
+ /**
920
+ * utf-8 encoded contents that will be copied on top of the workspace's filesystem
921
+ */
922
+ additionalFiles: {[filePath: string]: string};
923
+
924
+ }
925
+
926
+ export namespace AdditionalContentContext {
927
+ export function is(ctx: any): ctx is AdditionalContentContext {
928
+ return 'additionalFiles' in ctx;
929
+ }
930
+
931
+ export function hasDockerConfig(ctx: any, config: WorkspaceConfig): boolean {
932
+ return is(ctx) && ImageConfigFile.is(config.image) && !!ctx.additionalFiles[config.image.file];
933
+ }
934
+ }
935
+
887
936
  export interface CommitContext extends WorkspaceContext, Commit {
888
937
  /** @deprecated Moved to .repository.cloneUrl, left here for backwards-compatibility for old workspace contextes in the DB */
889
938
  cloneUrl?: string
@@ -959,6 +1008,19 @@ export interface Repository {
959
1008
  parent: Repository
960
1009
  }
961
1010
  }
1011
+ export interface Branch {
1012
+ name: string;
1013
+ commit: CommitInfo;
1014
+ htmlUrl: string;
1015
+ }
1016
+
1017
+ export interface CommitInfo {
1018
+ author: string;
1019
+ sha: string;
1020
+ commitMessage: string;
1021
+ authorAvatarUrl?: string;
1022
+ authorDate?: string;
1023
+ }
962
1024
 
963
1025
  export namespace Repository {
964
1026
  export function fullRepoName(repo: Repository): string {
@@ -1001,6 +1063,7 @@ export interface WorkspaceCreationResult {
1001
1063
  runningWorkspacePrebuild?: {
1002
1064
  prebuildID: string
1003
1065
  workspaceID: string
1066
+ instanceID: string
1004
1067
  starting: RunningWorkspacePrebuildStarting
1005
1068
  sameCluster: boolean
1006
1069
  }
@@ -1177,21 +1240,3 @@ export interface Terms {
1177
1240
  readonly content: string;
1178
1241
  readonly formElements?: object;
1179
1242
  }
1180
-
1181
- export interface Project {
1182
- id: string;
1183
- cloneUrl: string;
1184
- teamId: string;
1185
- appInstallationId: string;
1186
- creationTime: string;
1187
- /** This is a flag that triggers the HARD DELETION of this entity */
1188
- deleted?: boolean;
1189
- }
1190
-
1191
- export interface Team {
1192
- id: string;
1193
- name: string;
1194
- creationTime: string;
1195
- /** This is a flag that triggers the HARD DELETION of this entity */
1196
- deleted?: boolean;
1197
- }
@@ -4,7 +4,6 @@
4
4
  * See License-AGPL.txt in the project root for license information.
5
5
  */
6
6
 
7
- import { Without } from "./util/without";
8
7
  import uuidv4 = require("uuid/v4");
9
8
  import { Subscription } from "./accounting-protocol";
10
9
 
@@ -22,7 +21,7 @@ export interface TeamSubscription {
22
21
  }
23
22
 
24
23
  export namespace TeamSubscription {
25
- export const create = (ts: Without<TeamSubscription, 'id'>): TeamSubscription => {
24
+ export const create = (ts: Omit<TeamSubscription, 'id'>): TeamSubscription => {
26
25
  const withId = ts as TeamSubscription;
27
26
  withId.id = uuidv4();
28
27
  return withId;
@@ -49,7 +48,7 @@ export type TeamSubscriptionSlotAssigned = TeamSubscriptionSlot & TeamSubscripti
49
48
  export type TeamSubscriptionSlotState = 'unassigned' | 'assigned' | 'deactivated' | 'cancelled';
50
49
 
51
50
  export namespace TeamSubscriptionSlot {
52
- export const create = (ts: Without<TeamSubscriptionSlot, 'id'>): TeamSubscriptionSlot => {
51
+ export const create = (ts: Omit<TeamSubscriptionSlot, 'id'>): TeamSubscriptionSlot => {
53
52
  const withId = ts as TeamSubscriptionSlot;
54
53
  withId.id = uuidv4();
55
54
  return withId;
@@ -83,6 +82,9 @@ export namespace TeamSubscriptionSlot {
83
82
  }
84
83
 
85
84
  }
85
+ export const isActive = (slot: TeamSubscriptionSlot): boolean => {
86
+ return !slot.cancellationDate;
87
+ }
86
88
  }
87
89
 
88
90
  /**