@gitpod/gitpod-protocol 0.1.5-pd-gen47-patch-test.1 → 0.1.5-pd-ide-metrics.32

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 (126) hide show
  1. package/data/gitpod-schema.json +16 -0
  2. package/lib/admin-protocol.d.ts +4 -0
  3. package/lib/admin-protocol.d.ts.map +1 -1
  4. package/lib/admin-protocol.js.map +1 -1
  5. package/lib/attribution.d.ts +20 -0
  6. package/lib/attribution.d.ts.map +1 -0
  7. package/lib/attribution.js +40 -0
  8. package/lib/attribution.js.map +1 -0
  9. package/lib/blocked-repositories-protocol.d.ts +13 -0
  10. package/lib/blocked-repositories-protocol.d.ts.map +1 -0
  11. package/lib/blocked-repositories-protocol.js +8 -0
  12. package/lib/blocked-repositories-protocol.js.map +1 -0
  13. package/lib/context-url.js +1 -1
  14. package/lib/context-url.js.map +1 -1
  15. package/lib/experiments/always-default.d.ts +8 -0
  16. package/lib/experiments/always-default.d.ts.map +1 -0
  17. package/lib/experiments/always-default.js +20 -0
  18. package/lib/experiments/always-default.js.map +1 -0
  19. package/lib/experiments/configcat-server.d.ts +8 -0
  20. package/lib/experiments/configcat-server.d.ts.map +1 -0
  21. package/lib/experiments/configcat-server.js +35 -0
  22. package/lib/experiments/configcat-server.js.map +1 -0
  23. package/lib/experiments/configcat.d.ts +22 -0
  24. package/lib/experiments/configcat.d.ts.map +1 -0
  25. package/lib/experiments/configcat.js +53 -0
  26. package/lib/experiments/configcat.js.map +1 -0
  27. package/lib/experiments/types.d.ts +23 -0
  28. package/lib/experiments/types.d.ts.map +1 -0
  29. package/lib/experiments/types.js +10 -0
  30. package/lib/experiments/types.js.map +1 -0
  31. package/lib/gitpod-service.d.ts +23 -2
  32. package/lib/gitpod-service.d.ts.map +1 -1
  33. package/lib/gitpod-service.js +1 -1
  34. package/lib/gitpod-service.js.map +1 -1
  35. package/lib/index.d.ts +1 -0
  36. package/lib/index.d.ts.map +1 -1
  37. package/lib/index.js +1 -0
  38. package/lib/index.js.map +1 -1
  39. package/lib/installation-admin-protocol.d.ts +3 -0
  40. package/lib/installation-admin-protocol.d.ts.map +1 -1
  41. package/lib/installation-admin-protocol.js +1 -0
  42. package/lib/installation-admin-protocol.js.map +1 -1
  43. package/lib/messaging/client-call-metrics.d.ts +1 -17
  44. package/lib/messaging/client-call-metrics.d.ts.map +1 -1
  45. package/lib/messaging/client-call-metrics.js +1 -2
  46. package/lib/messaging/client-call-metrics.js.map +1 -1
  47. package/lib/messaging/error.d.ts +1 -0
  48. package/lib/messaging/error.d.ts.map +1 -1
  49. package/lib/messaging/error.js +2 -0
  50. package/lib/messaging/error.js.map +1 -1
  51. package/lib/protocol.d.ts +34 -1
  52. package/lib/protocol.d.ts.map +1 -1
  53. package/lib/protocol.js +42 -2
  54. package/lib/protocol.js.map +1 -1
  55. package/lib/teams-projects-protocol.d.ts +14 -0
  56. package/lib/teams-projects-protocol.d.ts.map +1 -1
  57. package/lib/teams-projects-protocol.js.map +1 -1
  58. package/lib/usage.d.ts +31 -0
  59. package/lib/usage.d.ts.map +1 -0
  60. package/lib/usage.js +14 -0
  61. package/lib/usage.js.map +1 -0
  62. package/lib/util/debug-app.d.ts +25 -0
  63. package/lib/util/debug-app.d.ts.map +1 -0
  64. package/lib/util/debug-app.js +100 -0
  65. package/lib/util/debug-app.js.map +1 -0
  66. package/lib/util/gitpod-host-url.d.ts +1 -0
  67. package/lib/util/gitpod-host-url.d.ts.map +1 -1
  68. package/lib/util/gitpod-host-url.js +3 -0
  69. package/lib/util/gitpod-host-url.js.map +1 -1
  70. package/lib/util/grpc.d.ts +19 -0
  71. package/lib/util/grpc.d.ts.map +1 -1
  72. package/lib/util/grpc.js +73 -1
  73. package/lib/util/grpc.js.map +1 -1
  74. package/lib/util/logging.d.ts.map +1 -1
  75. package/lib/util/logging.js +8 -1
  76. package/lib/util/logging.js.map +1 -1
  77. package/lib/util/timeutil.d.ts +1 -0
  78. package/lib/util/timeutil.d.ts.map +1 -1
  79. package/lib/util/timeutil.js +7 -1
  80. package/lib/util/timeutil.js.map +1 -1
  81. package/lib/webhook-event.d.ts +44 -0
  82. package/lib/webhook-event.d.ts.map +1 -0
  83. package/lib/webhook-event.js +8 -0
  84. package/lib/webhook-event.js.map +1 -0
  85. package/lib/workspace-class.d.ts +14 -0
  86. package/lib/workspace-class.d.ts.map +1 -0
  87. package/lib/workspace-class.js +8 -0
  88. package/lib/workspace-class.js.map +1 -0
  89. package/lib/workspace-cluster.d.ts +5 -7
  90. package/lib/workspace-cluster.d.ts.map +1 -1
  91. package/lib/workspace-cluster.js.map +1 -1
  92. package/lib/workspace-instance.d.ts +11 -0
  93. package/lib/workspace-instance.d.ts.map +1 -1
  94. package/lib/wsready.d.ts +3 -3
  95. package/lib/wsready.d.ts.map +1 -1
  96. package/lib/wsready.js +0 -2
  97. package/lib/wsready.js.map +1 -1
  98. package/package.json +12 -6
  99. package/pkg-yarn.lock +8 -5
  100. package/provenance-bundle.jsonl +1 -1
  101. package/src/admin-protocol.ts +7 -0
  102. package/src/attribution.ts +48 -0
  103. package/src/blocked-repositories-protocol.ts +13 -0
  104. package/src/context-url.ts +1 -1
  105. package/src/experiments/always-default.ts +24 -0
  106. package/src/experiments/configcat-server.ts +38 -0
  107. package/src/experiments/configcat.ts +58 -0
  108. package/src/experiments/types.ts +35 -0
  109. package/src/gitpod-service.ts +29 -1
  110. package/src/index.ts +1 -0
  111. package/src/installation-admin-protocol.ts +3 -0
  112. package/src/messaging/client-call-metrics.ts +1 -20
  113. package/src/messaging/error.ts +3 -0
  114. package/src/protocol.ts +85 -4
  115. package/src/teams-projects-protocol.ts +15 -0
  116. package/src/usage.ts +50 -0
  117. package/src/util/debug-app.ts +81 -0
  118. package/src/util/gitpod-host-url.ts +4 -0
  119. package/src/util/grpc.ts +89 -0
  120. package/src/util/logging.ts +11 -2
  121. package/src/util/timeutil.ts +6 -0
  122. package/src/webhook-event.ts +55 -0
  123. package/src/workspace-class.ts +14 -0
  124. package/src/workspace-cluster.ts +2 -4
  125. package/src/workspace-instance.ts +17 -0
  126. package/src/wsready.ts +5 -4
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Copyright (c) 2022 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
+ export type AttributionId = UserAttributionId | TeamAttributionId;
8
+ export type AttributionTarget = "user" | "team";
9
+
10
+ export interface UserAttributionId {
11
+ kind: "user";
12
+ userId: string;
13
+ }
14
+ export interface TeamAttributionId {
15
+ kind: "team";
16
+ teamId: string;
17
+ }
18
+
19
+ export namespace AttributionId {
20
+ const SEPARATOR = ":";
21
+
22
+ export function parse(s: string): UserAttributionId | TeamAttributionId | undefined {
23
+ if (!s) {
24
+ return undefined;
25
+ }
26
+ const parts = s.split(":");
27
+ if (parts.length !== 2) {
28
+ return undefined;
29
+ }
30
+ switch (parts[0]) {
31
+ case "user":
32
+ return { kind: "user", userId: parts[1] };
33
+ case "team":
34
+ return { kind: "team", teamId: parts[1] };
35
+ default:
36
+ return undefined;
37
+ }
38
+ }
39
+
40
+ export function render(id: AttributionId): string {
41
+ switch (id.kind) {
42
+ case "user":
43
+ return `user${SEPARATOR}${id.userId}`;
44
+ case "team":
45
+ return `team${SEPARATOR}${id.teamId}`;
46
+ }
47
+ }
48
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Copyright (c) 2022 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
+ export interface BlockedRepository {
8
+ id: number;
9
+ urlRegexp: string;
10
+ blockUser: boolean;
11
+ createdAt: string;
12
+ updatedAt: string;
13
+ }
@@ -38,7 +38,7 @@ export namespace ContextURL {
38
38
  try {
39
39
  return new URL(normalized);
40
40
  } catch (err) {
41
- console.error(`unable to parse URL from normalized contextURL: '${normalized}'`, err);
41
+ console.debug(`unable to parse URL from normalized contextURL: '${normalized}'`);
42
42
  }
43
43
  return undefined;
44
44
  }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Copyright (c) 2022 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
+ import { Attributes, Client } from "./types";
7
+
8
+ // AlwaysReturningDefaultValueClient is an implemention of an experiments.Client which performs no lookup/network operation
9
+ // and always returns the default value for a given experimentName.
10
+ // This client is used for non-SaaS version of Gitpod, in particular for self-hosted installations where external
11
+ // network connections are not desirable or even possible.
12
+ class AlwaysReturningDefaultValueClient implements Client {
13
+ getValueAsync<T>(experimentName: string, defaultValue: T, attributes: Attributes): Promise<T> {
14
+ return Promise.resolve(defaultValue);
15
+ }
16
+
17
+ dispose(): void {
18
+ // there is nothing to dispose, no-op.
19
+ }
20
+ }
21
+
22
+ export function newAlwaysReturningDefaultValueClient(): Client {
23
+ return new AlwaysReturningDefaultValueClient();
24
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Copyright (c) 2022 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 { Client } from "./types";
8
+ import * as configcat from "configcat-node";
9
+ import { LogLevel } from "configcat-common";
10
+ import { ConfigCatClient } from "./configcat";
11
+ import { newAlwaysReturningDefaultValueClient } from "./always-default";
12
+
13
+ let client: Client | undefined;
14
+
15
+ export function getExperimentsClientForBackend(): Client {
16
+ // We have already instantiated a client, we can just re-use it.
17
+ if (client !== undefined) {
18
+ return client;
19
+ }
20
+
21
+ // Retrieve SDK key from ENV Variable
22
+ const sdkKey = process.env.CONFIGCAT_SDK_KEY;
23
+
24
+ // Self-hosted installations do not set the ConfigCat SDK key, so always use a client which returns the default value.
25
+ if (sdkKey === undefined || sdkKey === "") {
26
+ client = newAlwaysReturningDefaultValueClient();
27
+ return client;
28
+ }
29
+
30
+ const configCatClient = configcat.createClient(sdkKey, {
31
+ pollIntervalSeconds: 3 * 60, // 3 minutes
32
+ logger: configcat.createConsoleLogger(LogLevel.Error),
33
+ maxInitWaitTimeSeconds: 0,
34
+ });
35
+
36
+ client = new ConfigCatClient(configCatClient);
37
+ return client;
38
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Copyright (c) 2022 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 { Attributes, Client } from "./types";
8
+ import { User as ConfigCatUser } from "configcat-common/lib/RolloutEvaluator";
9
+ import { IConfigCatClient } from "configcat-common/lib/ConfigCatClient";
10
+ import { User } from "../protocol";
11
+
12
+ export const USER_ID_ATTRIBUTE = "user_id";
13
+ export const PROJECT_ID_ATTRIBUTE = "project_id";
14
+ export const TEAM_ID_ATTRIBUTE = "team_id";
15
+ export const TEAM_IDS_ATTRIBUTE = "team_ids";
16
+ export const TEAM_NAME_ATTRIBUTE = "team_name";
17
+ export const TEAM_NAMES_ATTRIBUTE = "team_names";
18
+
19
+ export class ConfigCatClient implements Client {
20
+ private client: IConfigCatClient;
21
+
22
+ constructor(cc: IConfigCatClient) {
23
+ this.client = cc;
24
+ }
25
+
26
+ getValueAsync<T>(experimentName: string, defaultValue: T, attributes: Attributes): Promise<T> {
27
+ return this.client.getValueAsync(experimentName, defaultValue, attributesToUser(attributes));
28
+ }
29
+
30
+ dispose(): void {
31
+ return this.client.dispose();
32
+ }
33
+ }
34
+
35
+ export function attributesToUser(attributes: Attributes): ConfigCatUser {
36
+ const userId = attributes.user?.id || "";
37
+ const email = User.is(attributes.user) ? User.getPrimaryEmail(attributes.user) : attributes.user?.email || "";
38
+
39
+ const custom: { [key: string]: string } = {};
40
+ if (userId) {
41
+ custom[USER_ID_ATTRIBUTE] = userId;
42
+ }
43
+ if (attributes.projectId) {
44
+ custom[PROJECT_ID_ATTRIBUTE] = attributes.projectId;
45
+ }
46
+ if (attributes.teamId) {
47
+ custom[TEAM_ID_ATTRIBUTE] = attributes.teamId;
48
+ }
49
+ if (attributes.teamName) {
50
+ custom[TEAM_NAME_ATTRIBUTE] = attributes.teamName;
51
+ }
52
+ if (attributes.teams) {
53
+ custom[TEAM_NAMES_ATTRIBUTE] = attributes.teams.map((t) => t.name).join(",");
54
+ custom[TEAM_IDS_ATTRIBUTE] = attributes.teams.map((t) => t.id).join(",");
55
+ }
56
+
57
+ return new ConfigCatUser(userId, email, "", custom);
58
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Copyright (c) 2022 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 { User } from "../protocol";
8
+ import { Team } from "../teams-projects-protocol";
9
+
10
+ export const Client = Symbol("Client");
11
+
12
+ // Attributes define attributes which can be used to segment audiences.
13
+ // Set the attributes which you want to use to group audiences into.
14
+ export interface Attributes {
15
+ // user.id is mapped to ConfigCat's "identifier" + "custom.user_id"
16
+ user?: User | { id: string; email?: string };
17
+
18
+ // Currently selected Gitpod Project ID (mapped to "custom.project_id")
19
+ projectId?: string;
20
+
21
+ // Currently selected Gitpod Team ID (mapped to "custom.team_id")
22
+ teamId?: string;
23
+ // Currently selected Gitpod Team Name (mapped to "custom.team_name")
24
+ teamName?: string;
25
+
26
+ // All the Gitpod Teams that the user is a member (or owner) of (mapped to "custom.team_names" and "custom.team_ids")
27
+ teams?: Team[];
28
+ }
29
+
30
+ export interface Client {
31
+ getValueAsync<T>(experimentName: string, defaultValue: T, attributes: Attributes): Promise<T>;
32
+
33
+ // dispose will dispose of the client, no longer retrieving flags
34
+ dispose(): void;
35
+ }
@@ -24,6 +24,7 @@ import {
24
24
  GuessGitTokenScopesParams,
25
25
  GuessedGitTokenScopes,
26
26
  ProjectEnvVar,
27
+ PrebuiltWorkspace,
27
28
  UserSSHPublicKeyValue,
28
29
  SSHPublicKeyValue,
29
30
  } from "./protocol";
@@ -36,6 +37,7 @@ import {
36
37
  PrebuildWithStatus,
37
38
  StartPrebuildResult,
38
39
  PartialProject,
40
+ PrebuildEvent,
39
41
  } from "./teams-projects-protocol";
40
42
  import { JsonRpcProxy, JsonRpcServer } from "./messaging/proxy-factory";
41
43
  import { Disposable, CancellationTokenSource } from "vscode-jsonrpc";
@@ -58,6 +60,9 @@ import {
58
60
  import { RemotePageMessage, RemoteTrackMessage, RemoteIdentifyMessage } from "./analytics";
59
61
  import { IDEServer } from "./ide-protocol";
60
62
  import { InstallationAdminSettings, TelemetryData } from "./installation-admin-protocol";
63
+ import { Currency } from "./plans";
64
+ import { BillableSession, BillableSessionRequest } from "./usage";
65
+ import { SupportedWorkspaceClass } from "./workspace-class";
61
66
 
62
67
  export interface GitpodClient {
63
68
  onInstanceUpdate(instance: WorkspaceInstance): void;
@@ -178,7 +183,10 @@ export interface GitpodServer extends JsonRpcServer<GitpodClient>, AdminServer,
178
183
  getTeamProjects(teamId: string): Promise<Project[]>;
179
184
  getUserProjects(): Promise<Project[]>;
180
185
  getProjectOverview(projectId: string): Promise<Project.Overview | undefined>;
186
+ getPrebuildEvents(projectId: string): Promise<PrebuildEvent[]>;
181
187
  findPrebuilds(params: FindPrebuildsParams): Promise<PrebuildWithStatus[]>;
188
+ findPrebuildByWorkspaceID(workspaceId: string): Promise<PrebuiltWorkspace | undefined>;
189
+ getPrebuild(prebuildId: string): Promise<PrebuildWithStatus | undefined>;
182
190
  triggerPrebuild(projectId: string, branchName: string | null): Promise<StartPrebuildResult>;
183
191
  cancelPrebuild(projectId: string, prebuildId: string): Promise<void>;
184
192
  fetchProjectRepositoryConfiguration(projectId: string): Promise<string | undefined>;
@@ -278,12 +286,31 @@ export interface GitpodServer extends JsonRpcServer<GitpodClient>, AdminServer,
278
286
 
279
287
  getGithubUpgradeUrls(): Promise<GithubUpgradeURL[]>;
280
288
 
289
+ getStripePublishableKey(): Promise<string>;
290
+ getStripeSetupIntentClientSecret(): Promise<string>;
291
+ findStripeSubscriptionIdForTeam(teamId: string): Promise<string | undefined>;
292
+ subscribeTeamToStripe(teamId: string, setupIntentId: string, currency: Currency): Promise<void>;
293
+ getStripePortalUrlForTeam(teamId: string): Promise<string>;
294
+ getSpendingLimitForTeam(teamId: string): Promise<number | undefined>;
295
+ setSpendingLimitForTeam(teamId: string, spendingLimit: number): Promise<void>;
296
+
297
+ listBilledUsage(req: BillableSessionRequest): Promise<BillableSession[]>;
298
+
299
+ setUsageAttribution(usageAttribution: string): Promise<void>;
300
+
281
301
  /**
282
302
  * Analytics
283
303
  */
284
304
  trackEvent(event: RemoteTrackMessage): Promise<void>;
285
305
  trackLocation(event: RemotePageMessage): Promise<void>;
286
306
  identifyUser(event: RemoteIdentifyMessage): Promise<void>;
307
+
308
+ /**
309
+ * Frontend notifications
310
+ */
311
+ getNotifications(): Promise<string[]>;
312
+
313
+ getSupportedWorkspaceClasses(): Promise<SupportedWorkspaceClass[]>;
287
314
  }
288
315
 
289
316
  export interface RateLimiterError {
@@ -365,7 +392,7 @@ export const createServerMock = function <C extends GitpodClient, S extends Gitp
365
392
  get: (target: S, property: keyof S) => {
366
393
  const result = target[property];
367
394
  if (!result) {
368
- throw new Error(`Method ${property} not implemented`);
395
+ throw new Error(`Method ${String(property)} not implemented`);
369
396
  }
370
397
  return result;
371
398
  },
@@ -381,6 +408,7 @@ export interface SetWorkspaceTimeoutResult {
381
408
 
382
409
  export interface GetWorkspaceTimeoutResult {
383
410
  duration: WorkspaceTimeoutDuration;
411
+ durationRaw: string;
384
412
  canChange: boolean;
385
413
  }
386
414
 
package/src/index.ts CHANGED
@@ -20,3 +20,4 @@ export * from "./teams-projects-protocol";
20
20
  export * from "./snapshot-url";
21
21
  export * from "./oss-allowlist";
22
22
  export * from "./installation-admin-protocol";
23
+ export * from "./webhook-event";
@@ -8,6 +8,7 @@ import { v4 as uuidv4 } from "uuid";
8
8
 
9
9
  const InstallationAdminSettingsPrototype = {
10
10
  sendTelemetry: true,
11
+ sendCustomerID: true,
11
12
  };
12
13
 
13
14
  export type InstallationAdminSettings = typeof InstallationAdminSettingsPrototype;
@@ -28,6 +29,8 @@ export interface TelemetryData {
28
29
  totalUsers: number;
29
30
  totalWorkspaces: number;
30
31
  totalInstances: number;
32
+ licenseType: string;
33
+ customerID?: string;
31
34
  }
32
35
 
33
36
  export namespace InstallationAdmin {
@@ -6,26 +6,7 @@
6
6
 
7
7
  import { injectable } from "inversify";
8
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
- }
9
+ import { IClientCallMetrics, IGrpcCallMetricsLabels, IGrpcCallMetricsLabelsWithCode } from "../util/grpc";
29
10
 
30
11
  @injectable()
31
12
  export class PrometheusClientCallMetrics implements IClientCallMetrics {
@@ -62,6 +62,9 @@ export namespace ErrorCodes {
62
62
  // 490 Too Many Running Workspace
63
63
  export const TOO_MANY_RUNNING_WORKSPACES = 490;
64
64
 
65
+ // 500 Internal Server Error
66
+ export const INTERNAL_SERVER_ERROR = 500;
67
+
65
68
  // 501 EE Feature
66
69
  export const EE_FEATURE = 501;
67
70
 
package/src/protocol.ts CHANGED
@@ -45,6 +45,9 @@ export interface User {
45
45
  markedDeleted?: boolean;
46
46
 
47
47
  additionalData?: AdditionalUserData;
48
+
49
+ // Identifies an explicit team or user ID to which all the user's workspace usage should be attributed to (e.g. for billing purposes)
50
+ usageAttributionId?: string;
48
51
  }
49
52
 
50
53
  export namespace User {
@@ -70,11 +73,14 @@ export namespace User {
70
73
  }
71
74
 
72
75
  /**
73
- * Tries to return the primaryEmail of the first identity this user signed up with.
76
+ * Returns the stored email or if it doesn't exist returns the primaryEmail of the first identity this user signed up with.
74
77
  * @param user
75
78
  * @returns A primaryEmail, or undefined if there is none.
76
79
  */
77
80
  export function getPrimaryEmail(user: User): string | undefined {
81
+ if (user.additionalData?.profile?.emailAddress) {
82
+ return user.additionalData?.profile?.emailAddress;
83
+ }
78
84
  const identities = user.identities.filter((i) => !!i.primaryEmail);
79
85
  if (identities.length <= 0) {
80
86
  return undefined;
@@ -136,6 +142,50 @@ export namespace User {
136
142
  }
137
143
  user.additionalData.ideSettings = newIDESettings;
138
144
  }
145
+
146
+ export function getProfile(user: User): Profile {
147
+ return {
148
+ name: User.getName(user!) || "",
149
+ email: User.getPrimaryEmail(user!) || "",
150
+ company: user?.additionalData?.profile?.companyName,
151
+ avatarURL: user?.avatarUrl,
152
+ };
153
+ }
154
+
155
+ export function setProfile(user: User, profile: Profile): User {
156
+ user.fullName = profile.name;
157
+ user.avatarUrl = profile.avatarURL;
158
+
159
+ if (!user.additionalData) {
160
+ user.additionalData = {};
161
+ }
162
+ if (!user.additionalData.profile) {
163
+ user.additionalData.profile = {};
164
+ }
165
+ user.additionalData.profile.emailAddress = profile.email;
166
+ user.additionalData.profile.companyName = profile.company;
167
+ user.additionalData.profile.lastUpdatedDetailsNudge = new Date().toISOString();
168
+
169
+ return user;
170
+ }
171
+
172
+ // The actual Profile of a User
173
+ export interface Profile {
174
+ name: string;
175
+ email: string;
176
+ company?: string;
177
+ avatarURL?: string;
178
+ }
179
+ export namespace Profile {
180
+ export function hasChanges(before: Profile, after: Profile) {
181
+ return (
182
+ before.name !== after.name ||
183
+ before.email !== after.email ||
184
+ before.company !== after.company ||
185
+ before.avatarURL !== after.avatarURL
186
+ );
187
+ }
188
+ }
139
189
  }
140
190
 
141
191
  export interface AdditionalUserData {
@@ -150,9 +200,22 @@ export interface AdditionalUserData {
150
200
  oauthClientsApproved?: { [key: string]: string };
151
201
  // to remember GH Orgs the user installed/updated the GH App for
152
202
  knownGitHubOrgs?: string[];
153
-
154
203
  // Git clone URL pointing to the user's dotfile repo
155
204
  dotfileRepo?: string;
205
+ // preferred workspace classes
206
+ workspaceClasses?: WorkspaceClasses;
207
+ // additional user profile data
208
+ profile?: ProfileDetails;
209
+ }
210
+
211
+ // The format in which we store User Profiles in
212
+ export interface ProfileDetails {
213
+ // when was the last time the user updated their profile information or has been nudged to do so.
214
+ lastUpdatedDetailsNudge?: string;
215
+ // the user's company name
216
+ companyName?: string;
217
+ // the user's email
218
+ emailAddress?: string;
156
219
  }
157
220
 
158
221
  export interface EmailNotificationSettings {
@@ -171,6 +234,11 @@ export type IDESettings = {
171
234
  useLatestVersion?: boolean;
172
235
  };
173
236
 
237
+ export interface WorkspaceClasses {
238
+ regular: string;
239
+ prebuild: string;
240
+ }
241
+
174
242
  export interface UserPlatform {
175
243
  uid: string;
176
244
  userAgent: string;
@@ -205,6 +273,7 @@ export const WorkspaceFeatureFlags = {
205
273
  full_workspace_backup: undefined,
206
274
  fixed_resources: undefined,
207
275
  persistent_volume_claim: undefined,
276
+ protected_secrets: undefined,
208
277
  };
209
278
  export type NamedWorkspaceFeatureFlag = keyof typeof WorkspaceFeatureFlags;
210
279
 
@@ -552,6 +621,7 @@ export interface Snapshot {
552
621
 
553
622
  export interface VolumeSnapshot {
554
623
  id: string;
624
+ workspaceId: string;
555
625
  creationTime: string;
556
626
  volumeHandle: string;
557
627
  }
@@ -625,7 +695,7 @@ export interface Workspace {
625
695
 
626
696
  export type WorkspaceSoftDeletion = "user" | "gc";
627
697
 
628
- export type WorkspaceType = "regular" | "prebuild" | "probe";
698
+ export type WorkspaceType = "regular" | "prebuild" | "probe"; // TODO(gpl) Removed prove here
629
699
 
630
700
  export namespace Workspace {
631
701
  export function getFullRepositoryName(ws: Workspace): string | undefined {
@@ -701,6 +771,7 @@ export interface JetBrainsConfig {
701
771
  }
702
772
  export interface JetBrainsProductConfig {
703
773
  prebuilds?: JetBrainsPrebuilds;
774
+ vmoptions?: string;
704
775
  }
705
776
  export interface JetBrainsPrebuilds {
706
777
  version?: "stable" | "latest" | "both";
@@ -816,7 +887,9 @@ export interface PrebuiltWorkspace {
816
887
 
817
888
  export namespace PrebuiltWorkspace {
818
889
  export function isDone(pws: PrebuiltWorkspace) {
819
- return pws.state === "available" || pws.state === "timeout" || pws.state === "aborted";
890
+ return (
891
+ pws.state === "available" || pws.state === "timeout" || pws.state === "aborted" || pws.state === "failed"
892
+ );
820
893
  }
821
894
 
822
895
  export function isAvailable(pws: PrebuiltWorkspace) {
@@ -1409,3 +1482,11 @@ export interface Terms {
1409
1482
  readonly content: string;
1410
1483
  readonly formElements?: object;
1411
1484
  }
1485
+
1486
+ export interface CostCenter {
1487
+ readonly id: string;
1488
+ /**
1489
+ * Unit: credits
1490
+ */
1491
+ spendingLimit: number;
1492
+ }
@@ -7,6 +7,7 @@
7
7
  import { PrebuiltWorkspaceState } from "./protocol";
8
8
  import { v4 as uuidv4 } from "uuid";
9
9
  import { DeepPartial } from "./util/deep-partial";
10
+ import { WebhookEvent } from "./webhook-event";
10
11
 
11
12
  export interface ProjectConfig {
12
13
  ".gitpod.yml": string;
@@ -14,6 +15,8 @@ export interface ProjectConfig {
14
15
 
15
16
  export interface ProjectSettings {
16
17
  useIncrementalPrebuilds?: boolean;
18
+ usePersistentVolumeClaim?: boolean;
19
+ keepOutdatedPrebuildsRunning?: boolean;
17
20
  }
18
21
 
19
22
  export interface Project {
@@ -150,3 +153,15 @@ export interface TeamMembershipInvite {
150
153
  /** This is a flag that triggers the HARD DELETION of this entity */
151
154
  deleted?: boolean;
152
155
  }
156
+
157
+ export interface PrebuildEvent {
158
+ id: string;
159
+ creationTime: string;
160
+ status: WebhookEvent.Status | WebhookEvent.PrebuildStatus;
161
+ message?: string;
162
+ prebuildId?: string;
163
+ projectId?: string;
164
+ cloneUrl?: string;
165
+ branch?: string;
166
+ commit?: string;
167
+ }
package/src/usage.ts ADDED
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Copyright (c) 2022 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 { WorkspaceType } from "./protocol";
8
+
9
+ export interface BillableSession {
10
+ // The id of the one paying the bill
11
+ attributionId: string;
12
+
13
+ // Relevant for workspace type. When prebuild, shows "prebuild"
14
+ userId?: string;
15
+ teamId?: string;
16
+
17
+ instanceId: string;
18
+
19
+ workspaceId: string;
20
+
21
+ workspaceType: BillableWorkspaceType;
22
+
23
+ workspaceClass: string;
24
+
25
+ // When the workspace started
26
+ startTime: string;
27
+
28
+ // When the workspace ended. Not set when the workspace is still running.
29
+ endTime?: string;
30
+
31
+ // The credits used for this session
32
+ credits: number;
33
+
34
+ // TODO - maybe
35
+ projectId?: string;
36
+ }
37
+
38
+ export interface BillableSessionRequest {
39
+ attributionId: string;
40
+ startedTimeOrder: SortOrder;
41
+ from?: number;
42
+ to?: number;
43
+ }
44
+
45
+ export type BillableWorkspaceType = WorkspaceType;
46
+
47
+ export enum SortOrder {
48
+ Descending = 0,
49
+ Ascending = 1,
50
+ }