@gitpod/gitpod-protocol 0.1.5-pd-add-latest-jb.7 → 0.1.5-pd-gen47-patch-test.1

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 (282) hide show
  1. package/data/gitpod-schema.json +165 -4
  2. package/lib/accounting-protocol.d.ts +17 -10
  3. package/lib/accounting-protocol.d.ts.map +1 -1
  4. package/lib/accounting-protocol.js +30 -32
  5. package/lib/accounting-protocol.js.map +1 -1
  6. package/lib/admin-protocol.d.ts +4 -2
  7. package/lib/admin-protocol.d.ts.map +1 -1
  8. package/lib/admin-protocol.js.map +1 -1
  9. package/lib/analytics.d.ts +4 -5
  10. package/lib/analytics.d.ts.map +1 -1
  11. package/lib/analytics.js.map +1 -1
  12. package/lib/auth.d.ts.map +1 -1
  13. package/lib/context-url.d.ts +17 -5
  14. package/lib/context-url.d.ts.map +1 -1
  15. package/lib/context-url.js +57 -6
  16. package/lib/context-url.js.map +1 -1
  17. package/lib/context-url.spec.d.ts +2 -0
  18. package/lib/context-url.spec.d.ts.map +1 -1
  19. package/lib/context-url.spec.js +40 -4
  20. package/lib/context-url.spec.js.map +1 -1
  21. package/lib/email-protocol.d.ts +1 -1
  22. package/lib/email-protocol.d.ts.map +1 -1
  23. package/lib/email-protocol.js.map +1 -1
  24. package/lib/encryption/container-module.d.ts.map +1 -1
  25. package/lib/encryption/container-module.js +1 -1
  26. package/lib/encryption/container-module.js.map +1 -1
  27. package/lib/encryption/encryption-engine.d.ts.map +1 -1
  28. package/lib/encryption/encryption-engine.js +7 -7
  29. package/lib/encryption/encryption-engine.js.map +1 -1
  30. package/lib/encryption/encryption-engine.spec.d.ts.map +1 -1
  31. package/lib/encryption/encryption-engine.spec.js +2 -3
  32. package/lib/encryption/encryption-engine.spec.js.map +1 -1
  33. package/lib/encryption/encryption-service.d.ts.map +1 -1
  34. package/lib/encryption/encryption-service.js +1 -1
  35. package/lib/encryption/encryption-service.js.map +1 -1
  36. package/lib/encryption/key-provider.d.ts.map +1 -1
  37. package/lib/encryption/key-provider.js +7 -9
  38. package/lib/encryption/key-provider.js.map +1 -1
  39. package/lib/env.d.ts +0 -5
  40. package/lib/env.d.ts.map +1 -1
  41. package/lib/env.js +1 -20
  42. package/lib/env.js.map +1 -1
  43. package/lib/gitpod-file-parser.d.ts.map +1 -1
  44. package/lib/gitpod-file-parser.js +6 -6
  45. package/lib/gitpod-file-parser.js.map +1 -1
  46. package/lib/gitpod-file-parser.spec.js +42 -39
  47. package/lib/gitpod-file-parser.spec.js.map +1 -1
  48. package/lib/gitpod-service.d.ts +40 -26
  49. package/lib/gitpod-service.d.ts.map +1 -1
  50. package/lib/gitpod-service.js +39 -32
  51. package/lib/gitpod-service.js.map +1 -1
  52. package/lib/headless-workspace-log.d.ts +1 -0
  53. package/lib/headless-workspace-log.d.ts.map +1 -1
  54. package/lib/headless-workspace-log.js +2 -1
  55. package/lib/headless-workspace-log.js.map +1 -1
  56. package/lib/ide-frontend-service.d.ts +1 -1
  57. package/lib/ide-protocol.d.ts +6 -6
  58. package/lib/ide-protocol.d.ts.map +1 -1
  59. package/lib/index.d.ts +16 -16
  60. package/lib/installation-admin-protocol.d.ts +6 -0
  61. package/lib/installation-admin-protocol.d.ts.map +1 -1
  62. package/lib/installation-admin-protocol.js +2 -2
  63. package/lib/installation-admin-protocol.js.map +1 -1
  64. package/lib/license-protocol.d.ts +7 -0
  65. package/lib/license-protocol.d.ts.map +1 -1
  66. package/lib/license-protocol.js.map +1 -1
  67. package/lib/messaging/browser/connection.d.ts +1 -1
  68. package/lib/messaging/browser/connection.d.ts.map +1 -1
  69. package/lib/messaging/browser/connection.js +19 -19
  70. package/lib/messaging/browser/connection.js.map +1 -1
  71. package/lib/messaging/browser/window-connection.d.ts +4 -4
  72. package/lib/messaging/browser/window-connection.d.ts.map +1 -1
  73. package/lib/messaging/browser/window-connection.js +9 -6
  74. package/lib/messaging/browser/window-connection.js.map +1 -1
  75. package/lib/messaging/client-call-metrics.d.ts +2 -2
  76. package/lib/messaging/client-call-metrics.d.ts.map +1 -1
  77. package/lib/messaging/client-call-metrics.js +20 -20
  78. package/lib/messaging/client-call-metrics.js.map +1 -1
  79. package/lib/messaging/error.d.ts +1 -0
  80. package/lib/messaging/error.d.ts.map +1 -1
  81. package/lib/messaging/error.js +2 -0
  82. package/lib/messaging/error.js.map +1 -1
  83. package/lib/messaging/handler.d.ts.map +1 -1
  84. package/lib/messaging/handler.js +1 -1
  85. package/lib/messaging/node/connection.js +8 -8
  86. package/lib/messaging/node/connection.js.map +1 -1
  87. package/lib/messaging/proxy-factory.d.ts +1 -1
  88. package/lib/messaging/proxy-factory.d.ts.map +1 -1
  89. package/lib/messaging/proxy-factory.js +7 -9
  90. package/lib/messaging/proxy-factory.js.map +1 -1
  91. package/lib/payment-protocol.d.ts.map +1 -1
  92. package/lib/payment-protocol.js +1 -1
  93. package/lib/payment-protocol.js.map +1 -1
  94. package/lib/permission.d.ts +5 -2
  95. package/lib/permission.d.ts.map +1 -1
  96. package/lib/permission.js +30 -25
  97. package/lib/permission.js.map +1 -1
  98. package/lib/plans.d.ts +3 -3
  99. package/lib/plans.d.ts.map +1 -1
  100. package/lib/plans.js +206 -171
  101. package/lib/plans.js.map +1 -1
  102. package/lib/protocol.d.ts +107 -38
  103. package/lib/protocol.d.ts.map +1 -1
  104. package/lib/protocol.js +214 -88
  105. package/lib/protocol.js.map +1 -1
  106. package/{src/theia-plugins.ts → lib/protocol.spec.d.ts} +2 -6
  107. package/lib/protocol.spec.d.ts.map +1 -0
  108. package/lib/protocol.spec.js +127 -0
  109. package/lib/protocol.spec.js.map +1 -0
  110. package/lib/snapshot-url.spec.js.map +1 -1
  111. package/lib/team-subscription-protocol.d.ts +21 -3
  112. package/lib/team-subscription-protocol.d.ts.map +1 -1
  113. package/lib/team-subscription-protocol.js +16 -5
  114. package/lib/team-subscription-protocol.js.map +1 -1
  115. package/lib/teams-projects-protocol.d.ts +7 -3
  116. package/lib/teams-projects-protocol.d.ts.map +1 -1
  117. package/lib/teams-projects-protocol.js +1 -1
  118. package/lib/teams-projects-protocol.js.map +1 -1
  119. package/lib/typings/globals.d.ts +2 -2
  120. package/lib/typings/globals.d.ts.map +1 -1
  121. package/lib/util/analytics.d.ts.map +1 -1
  122. package/lib/util/analytics.js +12 -3
  123. package/lib/util/analytics.js.map +1 -1
  124. package/lib/util/async-iterator.d.ts.map +1 -1
  125. package/lib/util/async-iterator.js +3 -3
  126. package/lib/util/async-iterator.js.map +1 -1
  127. package/lib/util/cancelable.js.map +1 -1
  128. package/lib/util/date-time.js +6 -6
  129. package/lib/util/date-time.js.map +1 -1
  130. package/lib/util/deferred.js.map +1 -1
  131. package/lib/util/disposable.d.ts.map +1 -1
  132. package/lib/util/disposable.js +2 -2
  133. package/lib/util/disposable.js.map +1 -1
  134. package/lib/util/event.d.ts.map +1 -1
  135. package/lib/util/event.js +5 -3
  136. package/lib/util/event.js.map +1 -1
  137. package/lib/util/garbage-collected-cache.d.ts.map +1 -1
  138. package/lib/util/garbage-collected-cache.js +1 -1
  139. package/lib/util/garbage-collected-cache.js.map +1 -1
  140. package/lib/util/generate-workspace-id.d.ts +5 -0
  141. package/lib/util/generate-workspace-id.d.ts.map +1 -1
  142. package/lib/util/generate-workspace-id.js +446 -442
  143. package/lib/util/generate-workspace-id.js.map +1 -1
  144. package/lib/util/generate-workspace-id.spec.js +18 -7
  145. package/lib/util/generate-workspace-id.spec.js.map +1 -1
  146. package/lib/util/gitpod-cookie.d.ts +1 -1
  147. package/lib/util/gitpod-cookie.d.ts.map +1 -1
  148. package/lib/util/gitpod-cookie.js +0 -3
  149. package/lib/util/gitpod-cookie.js.map +1 -1
  150. package/lib/util/gitpod-host-url.d.ts.map +1 -1
  151. package/lib/util/gitpod-host-url.js +31 -29
  152. package/lib/util/gitpod-host-url.js.map +1 -1
  153. package/lib/util/gitpod-host-url.spec.d.ts.map +1 -1
  154. package/lib/util/gitpod-host-url.spec.js +15 -5
  155. package/lib/util/gitpod-host-url.spec.js.map +1 -1
  156. package/lib/util/grpc.d.ts.map +1 -1
  157. package/lib/util/grpc.js.map +1 -1
  158. package/lib/util/jaeger-client-types.d.ts.map +1 -1
  159. package/lib/util/logging.d.ts +1 -1
  160. package/lib/util/logging.d.ts.map +1 -1
  161. package/lib/util/logging.js +23 -24
  162. package/lib/util/logging.js.map +1 -1
  163. package/lib/util/make-link.js +5 -5
  164. package/lib/util/make-link.js.map +1 -1
  165. package/lib/util/parse-workspace-id.d.ts.map +1 -1
  166. package/lib/util/parse-workspace-id.js +1 -2
  167. package/lib/util/parse-workspace-id.js.map +1 -1
  168. package/lib/util/parse-workspace-id.spec.d.ts.map +1 -1
  169. package/lib/util/parse-workspace-id.spec.js.map +1 -1
  170. package/lib/util/queue.spec.js +9 -6
  171. package/lib/util/queue.spec.js.map +1 -1
  172. package/lib/util/semaphore.d.ts.map +1 -1
  173. package/lib/util/semaphore.js.map +1 -1
  174. package/lib/util/skip-if.d.ts.map +1 -1
  175. package/lib/util/skip-if.js.map +1 -1
  176. package/lib/util/timeutil.d.ts.map +1 -1
  177. package/lib/util/timeutil.js +2 -2
  178. package/lib/util/timeutil.js.map +1 -1
  179. package/lib/util/timeutil.spec.d.ts.map +1 -1
  180. package/lib/util/timeutil.spec.js.map +1 -1
  181. package/lib/util/tracing.d.ts +8 -8
  182. package/lib/util/tracing.d.ts.map +1 -1
  183. package/lib/util/tracing.js +19 -20
  184. package/lib/util/tracing.js.map +1 -1
  185. package/lib/util/tracing.spec.js +3 -3
  186. package/lib/util/tracing.spec.js.map +1 -1
  187. package/lib/util/workspace-port-authentication.d.ts +7 -7
  188. package/lib/util/workspace-port-authentication.d.ts.map +1 -1
  189. package/lib/util/workspace-port-authentication.js +8 -11
  190. package/lib/util/workspace-port-authentication.js.map +1 -1
  191. package/lib/workspace-cluster.d.ts +8 -3
  192. package/lib/workspace-cluster.d.ts.map +1 -1
  193. package/lib/workspace-cluster.js +16 -1
  194. package/lib/workspace-cluster.js.map +1 -1
  195. package/lib/workspace-instance.d.ts +8 -3
  196. package/lib/workspace-instance.d.ts.map +1 -1
  197. package/lib/wsready.d.ts +1 -1
  198. package/lib/wsready.d.ts.map +1 -1
  199. package/lib/wsready.js +2 -2
  200. package/package.json +2 -2
  201. package/pkg-yarn.lock +2 -2
  202. package/provenance-bundle.jsonl +1 -1
  203. package/src/accounting-protocol.ts +63 -51
  204. package/src/admin-protocol.ts +25 -21
  205. package/src/analytics.ts +26 -28
  206. package/src/auth.ts +2 -2
  207. package/src/context-url.spec.ts +37 -9
  208. package/src/context-url.ts +96 -40
  209. package/src/email-protocol.ts +5 -6
  210. package/src/encryption/container-module.ts +2 -3
  211. package/src/encryption/encryption-engine.spec.ts +9 -8
  212. package/src/encryption/encryption-engine.ts +14 -14
  213. package/src/encryption/encryption-service.ts +4 -5
  214. package/src/encryption/key-provider.ts +16 -19
  215. package/src/env.ts +0 -22
  216. package/src/gitpod-file-parser.spec.ts +55 -61
  217. package/src/gitpod-file-parser.ts +16 -17
  218. package/src/gitpod-service.ts +163 -108
  219. package/src/headless-workspace-log.ts +6 -4
  220. package/src/ide-frontend-service.ts +2 -2
  221. package/src/ide-protocol.ts +8 -8
  222. package/src/index.ts +16 -16
  223. package/src/installation-admin-protocol.ts +11 -4
  224. package/src/license-protocol.ts +12 -6
  225. package/src/messaging/browser/connection.ts +45 -47
  226. package/src/messaging/browser/window-connection.ts +39 -29
  227. package/src/messaging/client-call-metrics.ts +70 -71
  228. package/src/messaging/error.ts +4 -3
  229. package/src/messaging/handler.ts +6 -6
  230. package/src/messaging/node/connection.ts +8 -8
  231. package/src/messaging/proxy-factory.ts +23 -30
  232. package/src/oss-allowlist.ts +3 -3
  233. package/src/payment-protocol.ts +2 -2
  234. package/src/permission.ts +35 -32
  235. package/src/plans.ts +236 -189
  236. package/src/protocol.spec.ts +97 -0
  237. package/src/protocol.ts +407 -241
  238. package/src/snapshot-url.spec.ts +9 -7
  239. package/src/team-subscription-protocol.ts +57 -23
  240. package/src/teams-projects-protocol.ts +13 -8
  241. package/src/typings/globals.ts +4 -4
  242. package/src/util/analytics.ts +46 -24
  243. package/src/util/async-iterator.ts +4 -5
  244. package/src/util/cancelable.ts +3 -3
  245. package/src/util/date-time.ts +8 -8
  246. package/src/util/deferred.ts +6 -6
  247. package/src/util/disposable.ts +3 -6
  248. package/src/util/event.ts +9 -11
  249. package/src/util/garbage-collected-cache.ts +3 -6
  250. package/src/util/generate-workspace-id.spec.ts +26 -16
  251. package/src/util/generate-workspace-id.ts +460 -454
  252. package/src/util/gitpod-cookie.ts +8 -9
  253. package/src/util/gitpod-host-url.spec.ts +40 -13
  254. package/src/util/gitpod-host-url.ts +37 -34
  255. package/src/util/grpc.ts +1 -1
  256. package/src/util/jaeger-client-types.ts +2 -2
  257. package/src/util/logging.ts +49 -40
  258. package/src/util/make-link.ts +6 -7
  259. package/src/util/parse-workspace-id.spec.ts +17 -8
  260. package/src/util/parse-workspace-id.ts +5 -6
  261. package/src/util/queue.spec.ts +27 -25
  262. package/src/util/repeat.ts +1 -1
  263. package/src/util/semaphore.ts +4 -6
  264. package/src/util/skip-if.ts +9 -6
  265. package/src/util/timeutil.spec.ts +14 -15
  266. package/src/util/timeutil.ts +15 -11
  267. package/src/util/tracing.spec.ts +28 -23
  268. package/src/util/tracing.ts +58 -54
  269. package/src/util/workspace-port-authentication.ts +10 -13
  270. package/src/workspace-cluster.ts +24 -8
  271. package/src/workspace-instance.ts +40 -24
  272. package/src/wsready.ts +3 -3
  273. package/data/builtin-theia-plugins.json +0 -372
  274. package/lib/messaging/connection-error-handler.d.ts +0 -27
  275. package/lib/messaging/connection-error-handler.d.ts.map +0 -1
  276. package/lib/messaging/connection-error-handler.js +0 -34
  277. package/lib/messaging/connection-error-handler.js.map +0 -1
  278. package/lib/theia-plugins.d.ts +0 -11
  279. package/lib/theia-plugins.d.ts.map +0 -1
  280. package/lib/theia-plugins.js +0 -8
  281. package/lib/theia-plugins.js.map +0 -1
  282. package/src/messaging/connection-error-handler.ts +0 -62
package/src/protocol.ts CHANGED
@@ -7,26 +7,27 @@
7
7
  import { WorkspaceInstance, PortVisibility } from "./workspace-instance";
8
8
  import { RoleOrPermission } from "./permission";
9
9
  import { Project } from "./teams-projects-protocol";
10
+ import { createHash } from "crypto";
10
11
 
11
12
  export interface UserInfo {
12
- name?: string
13
+ name?: string;
13
14
  }
14
15
 
15
16
  export interface User {
16
17
  /** The user id */
17
- id: string
18
+ id: string;
18
19
 
19
20
  /** The timestamp when the user entry was created */
20
- creationDate: string
21
+ creationDate: string;
21
22
 
22
- avatarUrl?: string
23
+ avatarUrl?: string;
23
24
 
24
- name?: string
25
+ name?: string;
25
26
 
26
27
  /** Optional for backwards compatibility */
27
- fullName?: string
28
+ fullName?: string;
28
29
 
29
- identities: Identity[]
30
+ identities: Identity[];
30
31
 
31
32
  /**
32
33
  * Whether the user has been blocked to use our service, because of TOS violation for example.
@@ -48,34 +49,38 @@ export interface User {
48
49
 
49
50
  export namespace User {
50
51
  export function is(data: any): data is User {
51
- return data
52
- && data.hasOwnProperty('id')
53
- && data.hasOwnProperty('identities')
52
+ return data && data.hasOwnProperty("id") && data.hasOwnProperty("identities");
54
53
  }
55
54
  export function getIdentity(user: User, authProviderId: string): Identity | undefined {
56
- return user.identities.find(id => id.authProviderId === authProviderId);
55
+ return user.identities.find((id) => id.authProviderId === authProviderId);
57
56
  }
58
57
  export function censor(user: User): User {
59
58
  const res = { ...user };
60
- delete (res.additionalData);
61
- res.identities = res.identities.map(i => {
62
- delete (i.tokens);
59
+ delete res.additionalData;
60
+ res.identities = res.identities.map((i) => {
61
+ delete i.tokens;
63
62
 
64
63
  // The user field is not in the Identity shape, but actually exists on DBIdentity.
65
64
  // Trying to push this object out via JSON RPC will fail because of the cyclic nature
66
65
  // of this field.
67
- delete ((i as any).user);
66
+ delete (i as any).user;
68
67
  return i;
69
68
  });
70
69
  return res;
71
70
  }
72
- export function getPrimaryEmail(user: User): string {
73
- const identities = user.identities.filter(i => !!i.primaryEmail);
71
+
72
+ /**
73
+ * Tries to return the primaryEmail of the first identity this user signed up with.
74
+ * @param user
75
+ * @returns A primaryEmail, or undefined if there is none.
76
+ */
77
+ export function getPrimaryEmail(user: User): string | undefined {
78
+ const identities = user.identities.filter((i) => !!i.primaryEmail);
74
79
  if (identities.length <= 0) {
75
- throw new Error(`No identity with primary email for user: ${user.id}!`);
80
+ return undefined;
76
81
  }
77
82
 
78
- return identities[0].primaryEmail!;
83
+ return identities[0].primaryEmail || undefined;
79
84
  }
80
85
  export function getName(user: User): string | undefined {
81
86
  const name = user.fullName || user.name;
@@ -90,6 +95,47 @@ export namespace User {
90
95
  }
91
96
  return undefined;
92
97
  }
98
+
99
+ export function hasPreferredIde(user: User) {
100
+ return (
101
+ typeof user?.additionalData?.ideSettings?.defaultIde !== "undefined" ||
102
+ typeof user?.additionalData?.ideSettings?.useLatestVersion !== "undefined"
103
+ );
104
+ }
105
+
106
+ export function isOnboardingUser(user: User) {
107
+ return !hasPreferredIde(user);
108
+ }
109
+
110
+ export function migrationIDESettings(user: User) {
111
+ if (
112
+ !user?.additionalData?.ideSettings ||
113
+ Object.keys(user.additionalData.ideSettings).length === 0 ||
114
+ user.additionalData.ideSettings.settingVersion === "2.0"
115
+ ) {
116
+ return;
117
+ }
118
+ const newIDESettings: IDESettings = {
119
+ settingVersion: "2.0",
120
+ };
121
+ const ideSettings = user.additionalData.ideSettings;
122
+ if (ideSettings.useDesktopIde) {
123
+ if (ideSettings.defaultDesktopIde === "code-desktop") {
124
+ newIDESettings.defaultIde = "code-desktop";
125
+ } else if (ideSettings.defaultDesktopIde === "code-desktop-insiders") {
126
+ newIDESettings.defaultIde = "code-desktop";
127
+ newIDESettings.useLatestVersion = true;
128
+ } else {
129
+ newIDESettings.defaultIde = ideSettings.defaultDesktopIde;
130
+ newIDESettings.useLatestVersion = ideSettings.useLatestVersion;
131
+ }
132
+ } else {
133
+ const useLatest = ideSettings.defaultIde === "code-latest";
134
+ newIDESettings.defaultIde = "code";
135
+ newIDESettings.useLatestVersion = useLatest;
136
+ }
137
+ user.additionalData.ideSettings = newIDESettings;
138
+ }
93
139
  }
94
140
 
95
141
  export interface AdditionalUserData {
@@ -98,10 +144,10 @@ export interface AdditionalUserData {
98
144
  featurePreview?: boolean;
99
145
  ideSettings?: IDESettings;
100
146
  // key is the name of the news, string the iso date when it was seen
101
- whatsNewSeen?: { [key: string]: string }
147
+ whatsNewSeen?: { [key: string]: string };
102
148
  // key is the name of the OAuth client i.e. local app, string the iso date when it was approved
103
149
  // TODO(rl): provide a management UX to allow rescinding of approval
104
- oauthClientsApproved?: { [key: string]: string }
150
+ oauthClientsApproved?: { [key: string]: string };
105
151
  // to remember GH Orgs the user installed/updated the GH App for
106
152
  knownGitHubOrgs?: string[];
107
153
 
@@ -116,11 +162,14 @@ export interface EmailNotificationSettings {
116
162
  }
117
163
 
118
164
  export type IDESettings = {
119
- defaultIde?: string
120
- useDesktopIde?: boolean
121
- defaultDesktopIde?: string
122
- useLatestVersion?: boolean
123
- }
165
+ settingVersion?: string;
166
+ defaultIde?: string;
167
+ // DEPRECATED: Use defaultIde after `settingVersion: 2.0`, no more specialify desktop or browser.
168
+ useDesktopIde?: boolean;
169
+ // DEPRECATED: Same with useDesktopIde.
170
+ defaultDesktopIde?: string;
171
+ useLatestVersion?: boolean;
172
+ };
124
173
 
125
174
  export interface UserPlatform {
126
175
  uid: string;
@@ -152,8 +201,12 @@ export interface UserFeatureSettings {
152
201
  * The values of this type MUST MATCH enum values in WorkspaceFeatureFlag from ws-manager/client/core_pb.d.ts
153
202
  * If they don't we'll break things during workspace startup.
154
203
  */
155
- export const WorkspaceFeatureFlags = { "full_workspace_backup": undefined, "fixed_resources": undefined };
156
- export type NamedWorkspaceFeatureFlag = keyof (typeof WorkspaceFeatureFlags);
204
+ export const WorkspaceFeatureFlags = {
205
+ full_workspace_backup: undefined,
206
+ fixed_resources: undefined,
207
+ persistent_volume_claim: undefined,
208
+ };
209
+ export type NamedWorkspaceFeatureFlag = keyof typeof WorkspaceFeatureFlags;
157
210
 
158
211
  export interface EnvVarWithValue {
159
212
  name: string;
@@ -166,7 +219,7 @@ export interface ProjectEnvVarWithValue extends EnvVarWithValue {
166
219
  censored: boolean;
167
220
  }
168
221
 
169
- export type ProjectEnvVar = Omit<ProjectEnvVarWithValue, 'value'>;
222
+ export type ProjectEnvVar = Omit<ProjectEnvVarWithValue, "value">;
170
223
 
171
224
  export interface UserEnvVarValue extends EnvVarWithValue {
172
225
  id?: string;
@@ -179,6 +232,44 @@ export interface UserEnvVar extends UserEnvVarValue {
179
232
  }
180
233
 
181
234
  export namespace UserEnvVar {
235
+ /**
236
+ * @param variable
237
+ * @returns Either a string containing an error message or undefined.
238
+ */
239
+ export function validate(variable: UserEnvVarValue): string | undefined {
240
+ const name = variable.name;
241
+ const pattern = variable.repositoryPattern;
242
+ if (name.trim() === "") {
243
+ return "Name must not be empty.";
244
+ }
245
+ if (name.length > 255) {
246
+ return "Name too long. Maximum name length is 255 characters.";
247
+ }
248
+ if (!/^[a-zA-Z_]+[a-zA-Z0-9_]*$/.test(name)) {
249
+ return "Name must match /^[a-zA-Z_]+[a-zA-Z0-9_]*$/.";
250
+ }
251
+ if (variable.value.trim() === "") {
252
+ return "Value must not be empty.";
253
+ }
254
+ if (variable.value.length > 32767) {
255
+ return "Value too long. Maximum value length is 32767 characters.";
256
+ }
257
+ if (pattern.trim() === "") {
258
+ return "Scope must not be empty.";
259
+ }
260
+ const split = pattern.split("/");
261
+ if (split.length < 2) {
262
+ return "A scope must use the form 'organization/repo'.";
263
+ }
264
+ for (const name of split) {
265
+ if (name !== "*") {
266
+ if (!/^[a-zA-Z0-9_\-.\*]+$/.test(name)) {
267
+ return "Invalid scope segment. Only ASCII characters, numbers, -, _, . or * are allowed.";
268
+ }
269
+ }
270
+ }
271
+ return undefined;
272
+ }
182
273
 
183
274
  // DEPRECATED: Use ProjectEnvVar instead of repositoryPattern - https://github.com/gitpod-com/gitpod/issues/5322
184
275
  export function normalizeRepoPattern(pattern: string) {
@@ -199,7 +290,7 @@ export namespace UserEnvVar {
199
290
  if (repoPattern == "*") {
200
291
  score += 1;
201
292
  }
202
- if (ownerPattern == '*') {
293
+ if (ownerPattern == "*") {
203
294
  score += 2;
204
295
  }
205
296
  if (ownerPattern == "#" || repoPattern == "#") {
@@ -210,20 +301,20 @@ export namespace UserEnvVar {
210
301
 
211
302
  // DEPRECATED: Use ProjectEnvVar instead of repositoryPattern - https://github.com/gitpod-com/gitpod/issues/5322
212
303
  export function filter<T extends UserEnvVarValue>(vars: T[], owner: string, repo: string): T[] {
213
- let result = vars.filter(e => {
304
+ let result = vars.filter((e) => {
214
305
  const [ownerPattern, repoPattern] = splitRepositoryPattern(e.repositoryPattern);
215
- if (ownerPattern !== '*' && ownerPattern !== '#' && (!!owner && ownerPattern !== owner.toLocaleLowerCase())) {
306
+ if (ownerPattern !== "*" && ownerPattern !== "#" && !!owner && ownerPattern !== owner.toLocaleLowerCase()) {
216
307
  return false;
217
308
  }
218
- if (repoPattern !== '*' && repoPattern !== '#' && (!!repo && repoPattern !== repo.toLocaleLowerCase())) {
309
+ if (repoPattern !== "*" && repoPattern !== "#" && !!repo && repoPattern !== repo.toLocaleLowerCase()) {
219
310
  return false;
220
311
  }
221
312
  return true;
222
313
  });
223
314
 
224
315
  const resmap = new Map<string, T[]>();
225
- result.forEach(e => {
226
- const l = (resmap.get(e.name) || []);
316
+ result.forEach((e) => {
317
+ const l = resmap.get(e.name) || [];
227
318
  l.push(e);
228
319
  resmap.set(e.name, l);
229
320
  });
@@ -258,46 +349,107 @@ export namespace UserEnvVar {
258
349
 
259
350
  // DEPRECATED: Use ProjectEnvVar instead of repositoryPattern - https://github.com/gitpod-com/gitpod/issues/5322
260
351
  export function splitRepositoryPattern(repositoryPattern: string): string[] {
261
- const patterns = repositoryPattern.split('/');
262
- const repoPattern = patterns.slice(1).join('/')
352
+ const patterns = repositoryPattern.split("/");
353
+ const repoPattern = patterns.slice(1).join("/");
263
354
  const ownerPattern = patterns[0];
264
355
  return [ownerPattern, repoPattern];
265
356
  }
266
357
  }
267
358
 
268
- export interface GitpodToken {
359
+ export interface SSHPublicKeyValue {
360
+ name: string;
361
+ key: string;
362
+ }
363
+ export interface UserSSHPublicKey extends SSHPublicKeyValue {
364
+ id: string;
365
+ key: string;
366
+ userId: string;
367
+ fingerprint: string;
368
+ creationTime: string;
369
+ lastUsedTime?: string;
370
+ }
371
+
372
+ export type UserSSHPublicKeyValue = Omit<UserSSHPublicKey, "key" | "userId">;
373
+
374
+ export namespace SSHPublicKeyValue {
375
+ export function validate(value: SSHPublicKeyValue): string | undefined {
376
+ if (value.name.length === 0) {
377
+ return "Title must not be empty.";
378
+ }
379
+ if (value.name.length > 255) {
380
+ return "Title too long. Maximum value length is 255 characters.";
381
+ }
382
+ if (value.key.length === 0) {
383
+ return "Key must not be empty.";
384
+ }
385
+ try {
386
+ getData(value);
387
+ } catch (e) {
388
+ return "Key is invalid. You must supply a key in OpenSSH public key format.";
389
+ }
390
+ return;
391
+ }
269
392
 
393
+ export function getData(value: SSHPublicKeyValue) {
394
+ // Begins with 'ssh-rsa', 'ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384', 'ecdsa-sha2-nistp521', 'ssh-ed25519', 'sk-ecdsa-sha2-nistp256@openssh.com', or 'sk-ssh-ed25519@openssh.com'.
395
+ const regex =
396
+ /^(?<type>ssh-rsa|ecdsa-sha2-nistp256|ecdsa-sha2-nistp384|ecdsa-sha2-nistp521|ssh-ed25519|sk-ecdsa-sha2-nistp256@openssh\.com|sk-ssh-ed25519@openssh\.com) (?<key>.*?)( (?<email>.*?))?$/;
397
+ const resultGroup = regex.exec(value.key.trim());
398
+ if (!resultGroup) {
399
+ throw new Error("Key is invalid.");
400
+ }
401
+ return {
402
+ type: resultGroup.groups?.["type"] as string,
403
+ key: resultGroup.groups?.["key"] as string,
404
+ email: resultGroup.groups?.["email"] || undefined,
405
+ };
406
+ }
407
+
408
+ export function getFingerprint(value: SSHPublicKeyValue) {
409
+ const data = getData(value);
410
+ let buf = Buffer.from(data.key, "base64");
411
+ // gitlab style
412
+ // const hash = createHash("md5").update(buf).digest("hex");
413
+ // github style
414
+ const hash = createHash("sha256").update(buf).digest("base64");
415
+ return hash;
416
+ }
417
+
418
+ export const MAXIMUM_KEY_LENGTH = 5;
419
+ }
420
+
421
+ export interface GitpodToken {
270
422
  /** Hash value (SHA256) of the token (primary key). */
271
- tokenHash: string
423
+ tokenHash: string;
272
424
 
273
425
  /** Human readable name of the token */
274
- name?: string
426
+ name?: string;
275
427
 
276
428
  /** Token kind */
277
- type: GitpodTokenType
429
+ type: GitpodTokenType;
278
430
 
279
431
  /** The user the token belongs to. */
280
- user: User
432
+ user: User;
281
433
 
282
434
  /** Scopes (e.g. limition to read-only) */
283
- scopes: string[]
435
+ scopes: string[];
284
436
 
285
437
  /** Created timestamp */
286
- created: string
438
+ created: string;
287
439
 
288
440
  // token is deleted on the database and about to be collected by db-sync
289
- deleted?: boolean
441
+ deleted?: boolean;
290
442
  }
291
443
 
292
444
  export enum GitpodTokenType {
293
445
  API_AUTH_TOKEN = 0,
294
- MACHINE_AUTH_TOKEN = 1
446
+ MACHINE_AUTH_TOKEN = 1,
295
447
  }
296
448
 
297
449
  export interface OneTimeSecret {
298
- id: string
450
+ id: string;
299
451
 
300
- value: string
452
+ value: string;
301
453
 
302
454
  expirationTime: string;
303
455
 
@@ -329,13 +481,12 @@ export type IdentityLookup = Pick<Identity, "authProviderId" | "authId">;
329
481
 
330
482
  export namespace Identity {
331
483
  export function is(data: any): data is Identity {
332
- return data.hasOwnProperty('authProviderId')
333
- && data.hasOwnProperty('authId')
334
- && data.hasOwnProperty('authName')
484
+ return (
485
+ data.hasOwnProperty("authProviderId") && data.hasOwnProperty("authId") && data.hasOwnProperty("authName")
486
+ );
335
487
  }
336
488
  export function equals(id1: IdentityLookup, id2: IdentityLookup) {
337
- return id1.authProviderId === id2.authProviderId
338
- && id1.authId === id2.authId
489
+ return id1.authProviderId === id2.authProviderId && id1.authId === id2.authId;
339
490
  }
340
491
  }
341
492
 
@@ -399,7 +550,13 @@ export interface Snapshot {
399
550
  message?: string;
400
551
  }
401
552
 
402
- export type SnapshotState = 'pending' | 'available' | 'error';
553
+ export interface VolumeSnapshot {
554
+ id: string;
555
+ creationTime: string;
556
+ volumeHandle: string;
557
+ }
558
+
559
+ export type SnapshotState = "pending" | "available" | "error";
403
560
 
404
561
  export interface LayoutData {
405
562
  workspaceId: string;
@@ -428,13 +585,13 @@ export interface Workspace {
428
585
  * The resolved, fix name of the workspace image. We only use this
429
586
  * to access the logs during an image build.
430
587
  */
431
- imageNameResolved?: string
588
+ imageNameResolved?: string;
432
589
 
433
590
  /**
434
591
  * The resolved/built fixed named of the base image. This field is only set if the workspace
435
592
  * already has its base image built.
436
593
  */
437
- baseImageNameResolved?: string
594
+ baseImageNameResolved?: string;
438
595
 
439
596
  shareable?: boolean;
440
597
  pinned?: boolean;
@@ -471,17 +628,16 @@ export type WorkspaceSoftDeletion = "user" | "gc";
471
628
  export type WorkspaceType = "regular" | "prebuild" | "probe";
472
629
 
473
630
  export namespace Workspace {
474
-
475
631
  export function getFullRepositoryName(ws: Workspace): string | undefined {
476
632
  if (CommitContext.is(ws.context)) {
477
- return ws.context.repository.owner + '/' + ws.context.repository.name
633
+ return ws.context.repository.owner + "/" + ws.context.repository.name;
478
634
  }
479
635
  return undefined;
480
636
  }
481
637
 
482
638
  export function getFullRepositoryUrl(ws: Workspace): string | undefined {
483
639
  if (CommitContext.is(ws.context)) {
484
- return `https://${ws.context.repository.host}/${getFullRepositoryName(ws)}`
640
+ return `https://${ws.context.repository.host}/${getFullRepositoryName(ws)}`;
485
641
  }
486
642
  return undefined;
487
643
  }
@@ -515,59 +671,49 @@ export namespace Workspace {
515
671
  }
516
672
  }
517
673
 
518
- export interface PreparePluginUploadParams {
519
- fullPluginName: string;
520
- }
521
-
522
- export interface ResolvePluginsParams {
523
- config?: WorkspaceConfig
524
- builtins?: ResolvedPlugins
525
- vsxRegistryUrl?: string
526
- }
527
-
528
- export interface InstallPluginsParams {
529
- pluginIds: string[]
530
- }
531
-
532
- export interface UninstallPluginParams {
533
- pluginId: string;
534
- }
535
-
536
674
  export interface GuessGitTokenScopesParams {
537
- host: string
538
- repoUrl: string
539
- gitCommand: string
540
- currentToken: GitToken
675
+ host: string;
676
+ repoUrl: string;
677
+ gitCommand: string;
678
+ currentToken: GitToken;
541
679
  }
542
680
 
543
681
  export interface GitToken {
544
- token: string
545
- user: string
546
- scopes: string[]
682
+ token: string;
683
+ user: string;
684
+ scopes: string[];
547
685
  }
548
686
 
549
687
  export interface GuessedGitTokenScopes {
550
- message?: string
551
- scopes?: string[]
688
+ message?: string;
689
+ scopes?: string[];
552
690
  }
553
691
 
554
- export type ResolvedPluginKind = 'user' | 'workspace' | 'builtin';
555
-
556
- export interface ResolvedPlugins {
557
- [pluginId: string]: ResolvedPlugin | undefined
692
+ export interface VSCodeConfig {
693
+ extensions?: string[];
558
694
  }
559
695
 
560
- export interface ResolvedPlugin {
561
- fullPluginName: string;
562
- url: string;
563
- kind: ResolvedPluginKind;
696
+ export interface JetBrainsConfig {
697
+ intellij?: JetBrainsProductConfig;
698
+ goland?: JetBrainsProductConfig;
699
+ pycharm?: JetBrainsProductConfig;
700
+ phpstorm?: JetBrainsProductConfig;
701
+ }
702
+ export interface JetBrainsProductConfig {
703
+ prebuilds?: JetBrainsPrebuilds;
704
+ }
705
+ export interface JetBrainsPrebuilds {
706
+ version?: "stable" | "latest" | "both";
564
707
  }
565
708
 
566
- export interface VSCodeConfig {
567
- extensions?: string[];
709
+ export interface RepositoryCloneInformation {
710
+ url: string;
711
+ checkoutLocation?: string;
568
712
  }
569
713
 
570
714
  export interface WorkspaceConfig {
715
+ mainConfiguration?: string;
716
+ additionalRepositories?: RepositoryCloneInformation[];
571
717
  image?: ImageConfig;
572
718
  ports?: PortConfig[];
573
719
  tasks?: TaskConfig[];
@@ -576,6 +722,7 @@ export interface WorkspaceConfig {
576
722
  gitConfig?: { [config: string]: string };
577
723
  github?: GithubAppConfig;
578
724
  vscode?: VSCodeConfig;
725
+ jetbrains?: JetBrainsConfig;
579
726
 
580
727
  /** deprecated. Enabled by default **/
581
728
  experimentalNetwork?: boolean;
@@ -590,7 +737,7 @@ export interface WorkspaceConfig {
590
737
  * additional-content - config comes from additional content, usually provided through the project's configuration
591
738
  * default - our static catch-all default config
592
739
  */
593
- _origin?: 'repo' | 'project-db' | 'definitely-gp' | 'derived' | 'additional-content' | 'default';
740
+ _origin?: "repo" | "project-db" | "definitely-gp" | "derived" | "additional-content" | "default";
594
741
 
595
742
  /**
596
743
  * Set of automatically infered feature flags. That's not something the user can set, but
@@ -600,34 +747,33 @@ export interface WorkspaceConfig {
600
747
  }
601
748
 
602
749
  export interface GithubAppConfig {
603
- prebuilds?: GithubAppPrebuildConfig
750
+ prebuilds?: GithubAppPrebuildConfig;
604
751
  }
605
752
  export interface GithubAppPrebuildConfig {
606
- master?: boolean
607
- branches?: boolean
608
- pullRequests?: boolean
609
- pullRequestsFromForks?: boolean
610
- addCheck?: boolean | 'prevent-merge-on-error'
611
- addBadge?: boolean
612
- addLabel?: boolean | string
613
- addComment?: boolean
753
+ master?: boolean;
754
+ branches?: boolean;
755
+ pullRequests?: boolean;
756
+ pullRequestsFromForks?: boolean;
757
+ addCheck?: boolean | "prevent-merge-on-error";
758
+ addBadge?: boolean;
759
+ addLabel?: boolean | string;
760
+ addComment?: boolean;
614
761
  }
615
762
  export namespace GithubAppPrebuildConfig {
616
763
  export function is(obj: boolean | GithubAppPrebuildConfig): obj is GithubAppPrebuildConfig {
617
- return !(typeof obj === 'boolean');
764
+ return !(typeof obj === "boolean");
618
765
  }
619
766
  }
620
767
 
621
768
  export type WorkspaceImageSource = WorkspaceImageSourceDocker | WorkspaceImageSourceReference;
622
769
  export interface WorkspaceImageSourceDocker {
623
- dockerFilePath: string
624
- dockerFileHash: string
625
- dockerFileSource?: Commit
770
+ dockerFilePath: string;
771
+ dockerFileHash: string;
772
+ dockerFileSource?: Commit;
626
773
  }
627
774
  export namespace WorkspaceImageSourceDocker {
628
775
  export function is(obj: object): obj is WorkspaceImageSourceDocker {
629
- return 'dockerFileHash' in obj
630
- && 'dockerFilePath' in obj;
776
+ return "dockerFileHash" in obj && "dockerFilePath" in obj;
631
777
  }
632
778
  }
633
779
  export interface WorkspaceImageSourceReference {
@@ -636,21 +782,23 @@ export interface WorkspaceImageSourceReference {
636
782
  }
637
783
  export namespace WorkspaceImageSourceReference {
638
784
  export function is(obj: object): obj is WorkspaceImageSourceReference {
639
- return 'baseImageResolved' in obj;
785
+ return "baseImageResolved" in obj;
640
786
  }
641
787
  }
642
788
 
643
- export type PrebuiltWorkspaceState
789
+ export type PrebuiltWorkspaceState =
644
790
  // the prebuild is queued and may start at anytime
645
- = "queued"
791
+ | "queued"
646
792
  // the workspace prebuild is currently running (i.e. there's a workspace pod deployed)
647
793
  | "building"
648
- // the prebuild failed due to some issue with the system (e.g. missed a message, could not start workspace)
794
+ // the prebuild was aborted
649
795
  | "aborted"
650
796
  // the prebuild timed out
651
797
  | "timeout"
652
- // the prebuild has finished and a snapshot is available
653
- | "available";
798
+ // the prebuild has finished (even if a headless task failed) and a snapshot is available
799
+ | "available"
800
+ // the prebuild (headless workspace) failed due to some system error
801
+ | "failed";
654
802
 
655
803
  export interface PrebuiltWorkspace {
656
804
  id: string;
@@ -661,13 +809,14 @@ export interface PrebuiltWorkspace {
661
809
  buildWorkspaceId: string;
662
810
  creationTime: string;
663
811
  state: PrebuiltWorkspaceState;
812
+ statusVersion: number;
664
813
  error?: string;
665
814
  snapshot?: string;
666
815
  }
667
816
 
668
817
  export namespace PrebuiltWorkspace {
669
818
  export function isDone(pws: PrebuiltWorkspace) {
670
- return pws.state === "available" || pws.state === "timeout" || pws.state === 'aborted';
819
+ return pws.state === "available" || pws.state === "timeout" || pws.state === "aborted";
671
820
  }
672
821
 
673
822
  export function isAvailable(pws: PrebuiltWorkspace) {
@@ -686,18 +835,22 @@ export interface PrebuiltWorkspaceUpdatable {
686
835
  repo: string;
687
836
  isResolved: boolean;
688
837
  installationId: string;
838
+ /**
839
+ * the commitSHA of the commit that triggered the prebuild
840
+ */
841
+ commitSHA?: string;
689
842
  issue?: string;
690
843
  contextUrl?: string;
691
844
  }
692
845
 
693
846
  export interface WhitelistedRepository {
694
- url: string
695
- name: string
696
- description?: string
697
- avatar?: string
847
+ url: string;
848
+ name: string;
849
+ description?: string;
850
+ avatar?: string;
698
851
  }
699
852
 
700
- export type PortOnOpen = 'open-browser' | 'open-preview' | 'notify' | 'ignore';
853
+ export type PortOnOpen = "open-browser" | "open-preview" | "notify" | "ignore";
701
854
 
702
855
  export interface PortConfig {
703
856
  port: number;
@@ -708,7 +861,7 @@ export interface PortConfig {
708
861
  }
709
862
  export namespace PortConfig {
710
863
  export function is(config: any): config is PortConfig {
711
- return config && ('port' in config) && (typeof config.port === 'number');
864
+ return config && "port" in config && typeof config.port === "number";
712
865
  }
713
866
  }
714
867
 
@@ -718,7 +871,7 @@ export interface PortRangeConfig {
718
871
  }
719
872
  export namespace PortRangeConfig {
720
873
  export function is(config: any): config is PortRangeConfig {
721
- return config && ('port' in config) && (typeof config.port === 'string' || config.port instanceof String);
874
+ return config && "port" in config && (typeof config.port === "string" || config.port instanceof String);
722
875
  }
723
876
  }
724
877
 
@@ -729,32 +882,31 @@ export interface TaskConfig {
729
882
  prebuild?: string;
730
883
  command?: string;
731
884
  env?: { [env: string]: any };
732
- openIn?: 'bottom' | 'main' | 'left' | 'right';
733
- openMode?: 'split-top' | 'split-left' | 'split-right' | 'split-bottom' | 'tab-before' | 'tab-after';
885
+ openIn?: "bottom" | "main" | "left" | "right";
886
+ openMode?: "split-top" | "split-left" | "split-right" | "split-bottom" | "tab-before" | "tab-after";
734
887
  }
735
888
 
736
889
  export namespace TaskConfig {
737
890
  export function is(config: any): config is TaskConfig {
738
- return config
739
- && ('command' in config || 'init' in config || 'before' in config);
891
+ return config && ("command" in config || "init" in config || "before" in config);
740
892
  }
741
893
  }
742
894
 
743
895
  export namespace WorkspaceImageBuild {
744
- export type Phase = 'BaseImage' | 'GitpodLayer' | 'Error' | 'Done';
896
+ export type Phase = "BaseImage" | "GitpodLayer" | "Error" | "Done";
745
897
  export interface StateInfo {
746
- phase: Phase
747
- currentStep?: number
748
- maxSteps?: number
898
+ phase: Phase;
899
+ currentStep?: number;
900
+ maxSteps?: number;
749
901
  }
750
902
  export interface LogContent {
751
- text: string
752
- upToLine?: number
753
- isDiff?: boolean
903
+ text: string;
904
+ upToLine?: number;
905
+ isDiff?: boolean;
754
906
  }
755
907
  export type LogCallback = (info: StateInfo, content: LogContent | undefined) => void;
756
908
  export namespace LogLine {
757
- export const DELIMITER = '\r\n';
909
+ export const DELIMITER = "\r\n";
758
910
  export const DELIMITER_REGEX = /\r?\n/;
759
911
  }
760
912
  }
@@ -763,20 +915,18 @@ export type ImageConfig = ImageConfigString | ImageConfigFile;
763
915
  export type ImageConfigString = string;
764
916
  export namespace ImageConfigString {
765
917
  export function is(config: ImageConfig | undefined): config is ImageConfigString {
766
- return typeof config === 'string';
918
+ return typeof config === "string";
767
919
  }
768
-
769
920
  }
770
921
  export interface ImageConfigFile {
771
922
  // Path to the Dockerfile relative to repository root
772
- file: string,
923
+ file: string;
773
924
  // Path to the docker build context relative to repository root
774
- context?: string
925
+ context?: string;
775
926
  }
776
927
  export namespace ImageConfigFile {
777
928
  export function is(config: ImageConfig | undefined): config is ImageConfigFile {
778
- return typeof config === 'object'
779
- && 'file' in config;
929
+ return typeof config === "object" && "file" in config;
780
930
  }
781
931
  }
782
932
  export interface ExternalImageConfigFile extends ImageConfigFile {
@@ -784,14 +934,13 @@ export interface ExternalImageConfigFile extends ImageConfigFile {
784
934
  }
785
935
  export namespace ExternalImageConfigFile {
786
936
  export function is(config: any | undefined): config is ExternalImageConfigFile {
787
- return typeof config === 'object'
788
- && 'file' in config
789
- && 'externalSource' in config;
937
+ return typeof config === "object" && "file" in config && "externalSource" in config;
790
938
  }
791
939
  }
792
940
 
793
941
  export interface WorkspaceContext {
794
942
  title: string;
943
+ ref?: string;
795
944
  /** This contains the URL portion of the contextURL (which might contain other modifiers as well). It's optional because it's not set for older workspaces. */
796
945
  normalizedContextURL?: string;
797
946
  forceCreateNewWorkspace?: boolean;
@@ -800,8 +949,7 @@ export interface WorkspaceContext {
800
949
 
801
950
  export namespace WorkspaceContext {
802
951
  export function is(context: any): context is WorkspaceContext {
803
- return context
804
- && 'title' in context;
952
+ return context && "title" in context;
805
953
  }
806
954
  }
807
955
 
@@ -810,22 +958,17 @@ export interface WithSnapshot {
810
958
  }
811
959
  export namespace WithSnapshot {
812
960
  export function is(context: any): context is WithSnapshot {
813
- return context
814
- && 'snapshotBucketId' in context;
961
+ return context && "snapshotBucketId" in context;
815
962
  }
816
963
  }
817
964
 
818
- export interface WithPrebuild {
819
- snapshotBucketId: string;
965
+ export interface WithPrebuild extends WithSnapshot {
820
966
  prebuildWorkspaceId: string;
821
967
  wasPrebuilt: true;
822
968
  }
823
969
  export namespace WithPrebuild {
824
970
  export function is(context: any): context is WithPrebuild {
825
- return context
826
- && 'snapshotBucketId' in context
827
- && 'prebuildWorkspaceId' in context
828
- && 'wasPrebuilt' in context;
971
+ return context && WithSnapshot.is(context) && "prebuildWorkspaceId" in context && "wasPrebuilt" in context;
829
972
  }
830
973
  }
831
974
 
@@ -839,16 +982,14 @@ export interface WithDefaultConfig {
839
982
 
840
983
  export namespace WithDefaultConfig {
841
984
  export function is(context: any): context is WithDefaultConfig {
842
- return context
843
- && 'withDefaultConfig' in context
844
- && context.withDefaultConfig;
985
+ return context && "withDefaultConfig" in context && context.withDefaultConfig;
845
986
  }
846
987
 
847
988
  export function mark(ctx: WorkspaceContext): WorkspaceContext & WithDefaultConfig {
848
989
  return {
849
990
  ...ctx,
850
- withDefaultConfig: true
851
- }
991
+ withDefaultConfig: true,
992
+ };
852
993
  }
853
994
  }
854
995
 
@@ -858,23 +999,24 @@ export interface SnapshotContext extends WorkspaceContext, WithSnapshot {
858
999
 
859
1000
  export namespace SnapshotContext {
860
1001
  export function is(context: any): context is SnapshotContext {
861
- return context
862
- && WithSnapshot.is(context)
863
- && 'snapshotId' in context;
1002
+ return context && WithSnapshot.is(context) && "snapshotId" in context;
864
1003
  }
865
1004
  }
866
1005
 
867
1006
  export interface StartPrebuildContext extends WorkspaceContext {
868
1007
  actual: WorkspaceContext;
869
1008
  commitHistory?: string[];
1009
+ additionalRepositoryCommitHistories?: {
1010
+ cloneUrl: string;
1011
+ commitHistory: string[];
1012
+ }[];
870
1013
  project?: Project;
871
1014
  branch?: string;
872
1015
  }
873
1016
 
874
1017
  export namespace StartPrebuildContext {
875
1018
  export function is(context: any): context is StartPrebuildContext {
876
- return context
877
- && 'actual' in context;
1019
+ return context && "actual" in context;
878
1020
  }
879
1021
  }
880
1022
 
@@ -886,21 +1028,18 @@ export interface PrebuiltWorkspaceContext extends WorkspaceContext {
886
1028
 
887
1029
  export namespace PrebuiltWorkspaceContext {
888
1030
  export function is(context: any): context is PrebuiltWorkspaceContext {
889
- return context
890
- && 'originalContext' in context
891
- && 'prebuiltWorkspace' in context;
1031
+ return context && "originalContext" in context && "prebuiltWorkspace" in context;
892
1032
  }
893
1033
  }
894
1034
 
895
1035
  export interface WithReferrerContext extends WorkspaceContext {
896
- referrer: string
897
- referrerIde?: string
1036
+ referrer: string;
1037
+ referrerIde?: string;
898
1038
  }
899
1039
 
900
1040
  export namespace WithReferrerContext {
901
1041
  export function is(context: any): context is WithReferrerContext {
902
- return context
903
- && 'referrer' in context;
1042
+ return context && "referrer" in context;
904
1043
  }
905
1044
  }
906
1045
 
@@ -910,21 +1049,18 @@ export interface WithEnvvarsContext extends WorkspaceContext {
910
1049
 
911
1050
  export namespace WithEnvvarsContext {
912
1051
  export function is(context: any): context is WithEnvvarsContext {
913
- return context
914
- && 'envvars' in context
1052
+ return context && "envvars" in context;
915
1053
  }
916
1054
  }
917
1055
 
918
1056
  export interface WorkspaceProbeContext extends WorkspaceContext {
919
- responseURL: string
920
- responseToken: string
1057
+ responseURL: string;
1058
+ responseToken: string;
921
1059
  }
922
1060
 
923
1061
  export namespace WorkspaceProbeContext {
924
1062
  export function is(context: any): context is WorkspaceProbeContext {
925
- return context
926
- && 'responseURL' in context
927
- && 'responseToken' in context;
1063
+ return context && "responseURL" in context && "responseToken" in context;
928
1064
  }
929
1065
  }
930
1066
 
@@ -936,32 +1072,30 @@ export namespace RefType {
936
1072
  }
937
1073
  // This fallback is meant to handle the cases where (for historic reasons) ref is present but refType is missing
938
1074
  return commit.refType || "branch";
939
- }
1075
+ };
940
1076
  }
941
1077
 
942
1078
  export interface Commit {
943
- repository: Repository
944
- revision: string
1079
+ repository: Repository;
1080
+ revision: string;
945
1081
 
946
1082
  // Might contain either a branch or a tag (determined by refType)
947
- ref?: string
1083
+ ref?: string;
948
1084
 
949
1085
  // refType is only set if ref is present (and not for old workspaces, before this feature was added)
950
- refType?: RefType
1086
+ refType?: RefType;
951
1087
  }
952
1088
 
953
1089
  export interface AdditionalContentContext extends WorkspaceContext {
954
-
955
1090
  /**
956
1091
  * utf-8 encoded contents that will be copied on top of the workspace's filesystem
957
1092
  */
958
- additionalFiles: {[filePath: string]: string};
959
-
1093
+ additionalFiles: { [filePath: string]: string };
960
1094
  }
961
1095
 
962
1096
  export namespace AdditionalContentContext {
963
1097
  export function is(ctx: any): ctx is AdditionalContentContext {
964
- return 'additionalFiles' in ctx;
1098
+ return "additionalFiles" in ctx;
965
1099
  }
966
1100
 
967
1101
  export function hasDockerConfig(ctx: any, config: WorkspaceConfig): boolean {
@@ -969,16 +1103,49 @@ export namespace AdditionalContentContext {
969
1103
  }
970
1104
  }
971
1105
 
972
- export interface CommitContext extends WorkspaceContext, Commit {
1106
+ export interface CommitContext extends WorkspaceContext, GitCheckoutInfo {
973
1107
  /** @deprecated Moved to .repository.cloneUrl, left here for backwards-compatibility for old workspace contextes in the DB */
974
- cloneUrl?: string
1108
+ cloneUrl?: string;
1109
+
1110
+ /**
1111
+ * The clone and checkout information for additional repositories in case of multi-repo projects.
1112
+ */
1113
+ additionalRepositoryCheckoutInfo?: GitCheckoutInfo[];
1114
+ }
1115
+
1116
+ export namespace CommitContext {
1117
+ /**
1118
+ * Creates a hash for all the commits of the CommitContext and all sub-repo commit infos.
1119
+ * The hash is max 255 chars long.
1120
+ * @param commitContext
1121
+ * @returns hash for commitcontext
1122
+ */
1123
+ export function computeHash(commitContext: CommitContext): string {
1124
+ // for single commits we use the revision to be backward compatible.
1125
+ if (
1126
+ !commitContext.additionalRepositoryCheckoutInfo ||
1127
+ commitContext.additionalRepositoryCheckoutInfo.length === 0
1128
+ ) {
1129
+ return commitContext.revision;
1130
+ }
1131
+ const hasher = createHash("sha256");
1132
+ hasher.update(commitContext.revision);
1133
+ for (const info of commitContext.additionalRepositoryCheckoutInfo) {
1134
+ hasher.update(info.revision);
1135
+ }
1136
+ return hasher.digest("hex");
1137
+ }
1138
+ }
1139
+
1140
+ export interface GitCheckoutInfo extends Commit {
1141
+ checkoutLocation?: string;
1142
+ upstreamRemoteURI?: string;
1143
+ localBranch?: string;
975
1144
  }
976
1145
 
977
1146
  export namespace CommitContext {
978
1147
  export function is(commit: any): commit is CommitContext {
979
- return WorkspaceContext.is(commit)
980
- && 'repository' in commit
981
- && 'revision' in commit
1148
+ return WorkspaceContext.is(commit) && "repository" in commit && "revision" in commit;
982
1149
  }
983
1150
  }
984
1151
 
@@ -986,17 +1153,14 @@ export interface PullRequestContext extends CommitContext {
986
1153
  nr: number;
987
1154
  ref: string;
988
1155
  base: {
989
- repository: Repository
990
- ref: string
991
- }
1156
+ repository: Repository;
1157
+ ref: string;
1158
+ };
992
1159
  }
993
1160
 
994
1161
  export namespace PullRequestContext {
995
1162
  export function is(ctx: any): ctx is PullRequestContext {
996
- return CommitContext.is(ctx)
997
- && 'nr' in ctx
998
- && 'ref' in ctx
999
- && 'base' in ctx
1163
+ return CommitContext.is(ctx) && "nr" in ctx && "ref" in ctx && "base" in ctx;
1000
1164
  }
1001
1165
  }
1002
1166
 
@@ -1008,10 +1172,7 @@ export interface IssueContext extends CommitContext {
1008
1172
 
1009
1173
  export namespace IssueContext {
1010
1174
  export function is(ctx: any): ctx is IssueContext {
1011
- return CommitContext.is(ctx)
1012
- && 'nr' in ctx
1013
- && 'ref' in ctx
1014
- && 'localBranch' in ctx
1175
+ return CommitContext.is(ctx) && "nr" in ctx && "ref" in ctx && "localBranch" in ctx;
1015
1176
  }
1016
1177
  }
1017
1178
 
@@ -1022,9 +1183,7 @@ export interface NavigatorContext extends CommitContext {
1022
1183
 
1023
1184
  export namespace NavigatorContext {
1024
1185
  export function is(ctx: any): ctx is NavigatorContext {
1025
- return CommitContext.is(ctx)
1026
- && 'path' in ctx
1027
- && 'isFile' in ctx
1186
+ return CommitContext.is(ctx) && "path" in ctx && "isFile" in ctx;
1028
1187
  }
1029
1188
  }
1030
1189
 
@@ -1033,6 +1192,8 @@ export interface Repository {
1033
1192
  owner: string;
1034
1193
  name: string;
1035
1194
  cloneUrl: string;
1195
+ /* Optional kind to differentiate between repositories of orgs/groups/projects and personal repos. */
1196
+ repoKind?: string;
1036
1197
  description?: string;
1037
1198
  avatarUrl?: string;
1038
1199
  webUrl?: string;
@@ -1041,8 +1202,8 @@ export interface Repository {
1041
1202
  private?: boolean;
1042
1203
  fork?: {
1043
1204
  // The direct parent of this fork
1044
- parent: Repository
1045
- }
1205
+ parent: Repository;
1206
+ };
1046
1207
  }
1047
1208
  export interface Branch {
1048
1209
  name: string;
@@ -1067,21 +1228,19 @@ export namespace Repository {
1067
1228
  export interface WorkspaceInstancePortsChangedEvent {
1068
1229
  type: "PortsChanged";
1069
1230
  instanceID: string;
1070
- portsOpened: number[]
1071
- portsClosed: number[]
1231
+ portsOpened: number[];
1232
+ portsClosed: number[];
1072
1233
  }
1073
1234
 
1074
1235
  export namespace WorkspaceInstancePortsChangedEvent {
1075
-
1076
1236
  export function is(data: any): data is WorkspaceInstancePortsChangedEvent {
1077
1237
  return data && data.type == "PortsChanged";
1078
1238
  }
1079
-
1080
1239
  }
1081
1240
 
1082
1241
  export interface WorkspaceInfo {
1083
- workspace: Workspace
1084
- latestInstance?: WorkspaceInstance
1242
+ workspace: Workspace;
1243
+ latestInstance?: WorkspaceInstance;
1085
1244
  }
1086
1245
 
1087
1246
  export namespace WorkspaceInfo {
@@ -1097,35 +1256,36 @@ export interface WorkspaceCreationResult {
1097
1256
  workspaceURL?: string;
1098
1257
  existingWorkspaces?: WorkspaceInfo[];
1099
1258
  runningWorkspacePrebuild?: {
1100
- prebuildID: string
1101
- workspaceID: string
1102
- instanceID: string
1103
- starting: RunningWorkspacePrebuildStarting
1104
- sameCluster: boolean
1105
- }
1259
+ prebuildID: string;
1260
+ workspaceID: string;
1261
+ instanceID: string;
1262
+ starting: RunningWorkspacePrebuildStarting;
1263
+ sameCluster: boolean;
1264
+ };
1106
1265
  runningPrebuildWorkspaceID?: string;
1107
1266
  }
1108
- export type RunningWorkspacePrebuildStarting = 'queued' | 'starting' | 'running';
1267
+ export type RunningWorkspacePrebuildStarting = "queued" | "starting" | "running";
1109
1268
 
1110
1269
  export enum CreateWorkspaceMode {
1111
1270
  // Default returns a running prebuild if there is any, otherwise creates a new workspace (using a prebuild if one is available)
1112
- Default = 'default',
1271
+ Default = "default",
1113
1272
  // ForceNew creates a new workspace irrespective of any running prebuilds. This mode is guaranteed to actually create a workspace - but may degrade user experience as currently runnig prebuilds are ignored.
1114
- ForceNew = 'force-new',
1273
+ ForceNew = "force-new",
1115
1274
  // UsePrebuild polls the database waiting for a currently running prebuild to become available. This mode exists to handle the db-sync delay.
1116
- UsePrebuild = 'use-prebuild',
1275
+ UsePrebuild = "use-prebuild",
1117
1276
  // SelectIfRunning returns a list of currently running workspaces for the context URL if there are any, otherwise falls back to Default mode
1118
- SelectIfRunning = 'select-if-running',
1277
+ SelectIfRunning = "select-if-running",
1119
1278
  }
1120
1279
 
1121
1280
  export namespace WorkspaceCreationResult {
1122
1281
  export function is(data: any): data is WorkspaceCreationResult {
1123
- return data && (
1124
- 'createdWorkspaceId' in data
1125
- || 'existingWorkspaces' in data
1126
- || 'runningWorkspacePrebuild' in data
1127
- || 'runningPrebuildWorkspaceID' in data
1128
- )
1282
+ return (
1283
+ data &&
1284
+ ("createdWorkspaceId" in data ||
1285
+ "existingWorkspaces" in data ||
1286
+ "runningWorkspacePrebuild" in data ||
1287
+ "runningPrebuildWorkspaceID" in data)
1288
+ );
1129
1289
  }
1130
1290
  }
1131
1291
 
@@ -1159,7 +1319,7 @@ export interface AuthProviderInfo {
1159
1319
  readonly default: string[];
1160
1320
  readonly publicRepo: string[];
1161
1321
  readonly privateRepo: string[];
1162
- }
1322
+ };
1163
1323
  }
1164
1324
 
1165
1325
  export interface AuthProviderEntry {
@@ -1171,6 +1331,8 @@ export interface AuthProviderEntry {
1171
1331
  readonly status: AuthProviderEntry.Status;
1172
1332
 
1173
1333
  readonly oauth: OAuth2Config;
1334
+ /** A random string that is to change whenever oauth changes (enforced on DB level) */
1335
+ readonly oauthRevision?: string;
1174
1336
  }
1175
1337
 
1176
1338
  export interface OAuth2Config {
@@ -1183,23 +1345,27 @@ export interface OAuth2Config {
1183
1345
  readonly scopeSeparator?: string;
1184
1346
 
1185
1347
  readonly settingsUrl?: string;
1186
- readonly authorizationParams?: { [key: string]: string }
1348
+ readonly authorizationParams?: { [key: string]: string };
1187
1349
  readonly configURL?: string;
1188
1350
  }
1189
1351
 
1190
1352
  export namespace AuthProviderEntry {
1191
1353
  export type Type = "GitHub" | "GitLab" | string;
1192
1354
  export type Status = "pending" | "verified";
1193
- export type NewEntry = Pick<AuthProviderEntry, "ownerId" | "host" | "type"> & { clientId?: string, clientSecret?: string };
1194
- export type UpdateEntry = Pick<AuthProviderEntry, "id" | "ownerId"> & Pick<OAuth2Config, "clientId" | "clientSecret">;
1355
+ export type NewEntry = Pick<AuthProviderEntry, "ownerId" | "host" | "type"> & {
1356
+ clientId?: string;
1357
+ clientSecret?: string;
1358
+ };
1359
+ export type UpdateEntry = Pick<AuthProviderEntry, "id" | "ownerId"> &
1360
+ Pick<OAuth2Config, "clientId" | "clientSecret">;
1195
1361
  export function redact(entry: AuthProviderEntry): AuthProviderEntry {
1196
1362
  return {
1197
1363
  ...entry,
1198
1364
  oauth: {
1199
1365
  ...entry.oauth,
1200
- clientSecret: "redacted"
1201
- }
1202
- }
1366
+ clientSecret: "redacted",
1367
+ },
1368
+ };
1203
1369
  }
1204
1370
  }
1205
1371