@gitpod/gitpod-protocol 0.1.5-wth-test.41 → 0.1.5-wth-test.80

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 (140) hide show
  1. package/data/gitpod-schema.json +18 -3
  2. package/lib/admin-protocol.d.ts +12 -1
  3. package/lib/admin-protocol.d.ts.map +1 -1
  4. package/lib/admin-protocol.js.map +1 -1
  5. package/lib/analytics.d.ts +4 -5
  6. package/lib/analytics.d.ts.map +1 -1
  7. package/lib/context-url.d.ts +18 -5
  8. package/lib/context-url.d.ts.map +1 -1
  9. package/lib/context-url.js +58 -5
  10. package/lib/context-url.js.map +1 -1
  11. package/lib/context-url.spec.d.ts +2 -0
  12. package/lib/context-url.spec.d.ts.map +1 -1
  13. package/lib/context-url.spec.js +25 -4
  14. package/lib/context-url.spec.js.map +1 -1
  15. package/lib/gitpod-service.d.ts +33 -6
  16. package/lib/gitpod-service.d.ts.map +1 -1
  17. package/lib/gitpod-service.js +4 -2
  18. package/lib/gitpod-service.js.map +1 -1
  19. package/lib/ide-protocol.d.ts +105 -0
  20. package/lib/ide-protocol.d.ts.map +1 -0
  21. package/lib/ide-protocol.js +8 -0
  22. package/lib/ide-protocol.js.map +1 -0
  23. package/lib/index.d.ts +2 -0
  24. package/lib/index.d.ts.map +1 -1
  25. package/lib/index.js +2 -0
  26. package/lib/index.js.map +1 -1
  27. package/lib/installation-admin-protocol.d.ts +27 -0
  28. package/lib/installation-admin-protocol.d.ts.map +1 -0
  29. package/lib/installation-admin-protocol.js +30 -0
  30. package/lib/installation-admin-protocol.js.map +1 -0
  31. package/lib/messaging/error.d.ts +1 -0
  32. package/lib/messaging/error.d.ts.map +1 -1
  33. package/lib/messaging/error.js +2 -0
  34. package/lib/messaging/error.js.map +1 -1
  35. package/lib/messaging/node/connection.d.ts +1 -17
  36. package/lib/messaging/node/connection.d.ts.map +1 -1
  37. package/lib/messaging/node/connection.js +21 -57
  38. package/lib/messaging/node/connection.js.map +1 -1
  39. package/lib/oss-allowlist.d.ts +14 -0
  40. package/lib/oss-allowlist.d.ts.map +1 -0
  41. package/lib/oss-allowlist.js +8 -0
  42. package/lib/oss-allowlist.js.map +1 -0
  43. package/lib/permission.d.ts +7 -1
  44. package/lib/permission.d.ts.map +1 -1
  45. package/lib/permission.js +24 -4
  46. package/lib/permission.js.map +1 -1
  47. package/lib/protocol.d.ts +28 -40
  48. package/lib/protocol.d.ts.map +1 -1
  49. package/lib/protocol.js +16 -4
  50. package/lib/protocol.js.map +1 -1
  51. package/lib/teams-projects-protocol.d.ts +10 -0
  52. package/lib/teams-projects-protocol.d.ts.map +1 -1
  53. package/lib/teams-projects-protocol.js +7 -0
  54. package/lib/teams-projects-protocol.js.map +1 -1
  55. package/lib/util/analytics.js +12 -3
  56. package/lib/util/analytics.js.map +1 -1
  57. package/lib/util/garbage-collected-cache.d.ts +1 -0
  58. package/lib/util/garbage-collected-cache.d.ts.map +1 -1
  59. package/lib/util/garbage-collected-cache.js +5 -1
  60. package/lib/util/garbage-collected-cache.js.map +1 -1
  61. package/lib/util/generate-workspace-id.d.ts +1 -1
  62. package/lib/util/generate-workspace-id.d.ts.map +1 -1
  63. package/lib/util/generate-workspace-id.js +19 -2
  64. package/lib/util/generate-workspace-id.js.map +1 -1
  65. package/lib/util/generate-workspace-id.spec.js +24 -0
  66. package/lib/util/generate-workspace-id.spec.js.map +1 -1
  67. package/lib/util/gitpod-host-url.d.ts +0 -1
  68. package/lib/util/gitpod-host-url.d.ts.map +1 -1
  69. package/lib/util/gitpod-host-url.js +3 -6
  70. package/lib/util/gitpod-host-url.js.map +1 -1
  71. package/lib/util/jaeger-client-types.d.ts +68 -0
  72. package/lib/util/jaeger-client-types.d.ts.map +1 -0
  73. package/lib/util/jaeger-client-types.js +8 -0
  74. package/lib/util/jaeger-client-types.js.map +1 -0
  75. package/lib/util/parse-workspace-id.js +1 -1
  76. package/lib/util/parse-workspace-id.js.map +1 -1
  77. package/lib/util/repeat.d.ts +15 -0
  78. package/lib/util/repeat.d.ts.map +1 -0
  79. package/lib/util/repeat.js +55 -0
  80. package/lib/util/repeat.js.map +1 -0
  81. package/lib/util/tracing.d.ts +51 -5
  82. package/lib/util/tracing.d.ts.map +1 -1
  83. package/lib/util/tracing.js +156 -17
  84. package/lib/util/tracing.js.map +1 -1
  85. package/lib/util/tracing.spec.d.ts +7 -0
  86. package/lib/util/tracing.spec.d.ts.map +1 -0
  87. package/lib/util/tracing.spec.js +121 -0
  88. package/lib/util/tracing.spec.js.map +1 -0
  89. package/lib/workspace-cluster.d.ts +9 -7
  90. package/lib/workspace-cluster.d.ts.map +1 -1
  91. package/lib/workspace-cluster.js +18 -1
  92. package/lib/workspace-cluster.js.map +1 -1
  93. package/lib/workspace-instance.d.ts +19 -0
  94. package/lib/workspace-instance.d.ts.map +1 -1
  95. package/package.json +5 -3
  96. package/pkg-yarn.lock +2 -2
  97. package/provenance-bundle.jsonl +2 -0
  98. package/src/admin-protocol.ts +19 -5
  99. package/src/analytics.ts +4 -6
  100. package/src/context-url.spec.ts +18 -4
  101. package/src/context-url.ts +62 -6
  102. package/src/gitpod-service.ts +41 -10
  103. package/src/ide-frontend-service.ts +1 -1
  104. package/src/ide-protocol.ts +119 -0
  105. package/src/index.ts +2 -0
  106. package/src/installation-admin-protocol.ts +42 -0
  107. package/src/messaging/error.ts +3 -0
  108. package/src/messaging/node/connection.ts +21 -68
  109. package/src/oss-allowlist.ts +15 -0
  110. package/src/permission.ts +22 -3
  111. package/src/protocol.ts +45 -44
  112. package/src/teams-projects-protocol.ts +16 -1
  113. package/src/util/analytics.ts +21 -3
  114. package/src/util/garbage-collected-cache.ts +7 -1
  115. package/src/util/generate-workspace-id.spec.ts +17 -0
  116. package/src/util/generate-workspace-id.ts +20 -2
  117. package/src/util/gitpod-host-url.ts +4 -8
  118. package/src/util/jaeger-client-types.ts +102 -0
  119. package/src/util/parse-workspace-id.ts +1 -1
  120. package/src/util/repeat.ts +45 -0
  121. package/src/util/tracing.spec.ts +83 -0
  122. package/src/util/tracing.ts +183 -17
  123. package/src/workspace-cluster.ts +17 -9
  124. package/src/workspace-instance.ts +20 -0
  125. package/lib/messaging/connection-error-handler.d.ts +0 -27
  126. package/lib/messaging/connection-error-handler.d.ts.map +0 -1
  127. package/lib/messaging/connection-error-handler.js +0 -34
  128. package/lib/messaging/connection-error-handler.js.map +0 -1
  129. package/lib/util/repeater.d.ts +0 -22
  130. package/lib/util/repeater.d.ts.map +0 -1
  131. package/lib/util/repeater.js +0 -65
  132. package/lib/util/repeater.js.map +0 -1
  133. package/lib/util/safe-promise.d.ts +0 -11
  134. package/lib/util/safe-promise.d.ts.map +0 -1
  135. package/lib/util/safe-promise.js +0 -31
  136. package/lib/util/safe-promise.js.map +0 -1
  137. package/src/messaging/connection-error-handler.ts +0 -62
  138. package/src/util/jaeger-client.d.ts +0 -105
  139. package/src/util/repeater.ts +0 -49
  140. package/src/util/safe-promise.ts +0 -26
package/src/protocol.ts CHANGED
@@ -104,6 +104,9 @@ export interface AdditionalUserData {
104
104
  oauthClientsApproved?: { [key: string]: string }
105
105
  // to remember GH Orgs the user installed/updated the GH App for
106
106
  knownGitHubOrgs?: string[];
107
+
108
+ // Git clone URL pointing to the user's dotfile repo
109
+ dotfileRepo?: string;
107
110
  }
108
111
 
109
112
  export interface EmailNotificationSettings {
@@ -116,6 +119,7 @@ export type IDESettings = {
116
119
  defaultIde?: string
117
120
  useDesktopIde?: boolean
118
121
  defaultDesktopIde?: string
122
+ useLatestVersion?: boolean
119
123
  }
120
124
 
121
125
  export interface UserPlatform {
@@ -151,12 +155,23 @@ export interface UserFeatureSettings {
151
155
  export const WorkspaceFeatureFlags = { "full_workspace_backup": undefined, "fixed_resources": undefined };
152
156
  export type NamedWorkspaceFeatureFlag = keyof (typeof WorkspaceFeatureFlags);
153
157
 
154
- export interface UserEnvVarValue {
155
- id?: string;
158
+ export interface EnvVarWithValue {
156
159
  name: string;
157
- repositoryPattern: string;
158
160
  value: string;
159
161
  }
162
+
163
+ export interface ProjectEnvVarWithValue extends EnvVarWithValue {
164
+ id: string;
165
+ projectId: string;
166
+ censored: boolean;
167
+ }
168
+
169
+ export type ProjectEnvVar = Omit<ProjectEnvVarWithValue, 'value'>;
170
+
171
+ export interface UserEnvVarValue extends EnvVarWithValue {
172
+ id?: string;
173
+ repositoryPattern: string; // DEPRECATED: Use ProjectEnvVar instead of repositoryPattern - https://github.com/gitpod-com/gitpod/issues/5322
174
+ }
160
175
  export interface UserEnvVar extends UserEnvVarValue {
161
176
  id: string;
162
177
  userId: string;
@@ -165,10 +180,12 @@ export interface UserEnvVar extends UserEnvVarValue {
165
180
 
166
181
  export namespace UserEnvVar {
167
182
 
183
+ // DEPRECATED: Use ProjectEnvVar instead of repositoryPattern - https://github.com/gitpod-com/gitpod/issues/5322
168
184
  export function normalizeRepoPattern(pattern: string) {
169
185
  return pattern.toLocaleLowerCase();
170
186
  }
171
187
 
188
+ // DEPRECATED: Use ProjectEnvVar instead of repositoryPattern - https://github.com/gitpod-com/gitpod/issues/5322
172
189
  export function score(value: UserEnvVarValue): number {
173
190
  // We use a score to enforce precedence:
174
191
  // value/value = 0
@@ -191,6 +208,7 @@ export namespace UserEnvVar {
191
208
  return score;
192
209
  }
193
210
 
211
+ // DEPRECATED: Use ProjectEnvVar instead of repositoryPattern - https://github.com/gitpod-com/gitpod/issues/5322
194
212
  export function filter<T extends UserEnvVarValue>(vars: T[], owner: string, repo: string): T[] {
195
213
  let result = vars.filter(e => {
196
214
  const [ownerPattern, repoPattern] = splitRepositoryPattern(e.repositoryPattern);
@@ -238,10 +256,11 @@ export namespace UserEnvVar {
238
256
  return result;
239
257
  }
240
258
 
259
+ // DEPRECATED: Use ProjectEnvVar instead of repositoryPattern - https://github.com/gitpod-com/gitpod/issues/5322
241
260
  export function splitRepositoryPattern(repositoryPattern: string): string[] {
242
261
  const patterns = repositoryPattern.split('/');
243
- const repoPattern = patterns.pop() || "";
244
- const ownerPattern = patterns.join('/');
262
+ const repoPattern = patterns.slice(1).join('/')
263
+ const ownerPattern = patterns[0];
245
264
  return [ownerPattern, repoPattern];
246
265
  }
247
266
  }
@@ -558,7 +577,7 @@ export interface WorkspaceConfig {
558
577
  github?: GithubAppConfig;
559
578
  vscode?: VSCodeConfig;
560
579
 
561
- /** tailscale demo */
580
+ /** deprecated. Enabled by default **/
562
581
  experimentalNetwork?: boolean;
563
582
 
564
583
  /**
@@ -588,7 +607,7 @@ export interface GithubAppPrebuildConfig {
588
607
  branches?: boolean
589
608
  pullRequests?: boolean
590
609
  pullRequestsFromForks?: boolean
591
- addCheck?: boolean
610
+ addCheck?: boolean | 'prevent-merge-on-error'
592
611
  addBadge?: boolean
593
612
  addLabel?: boolean | string
594
613
  addComment?: boolean
@@ -684,6 +703,8 @@ export interface PortConfig {
684
703
  port: number;
685
704
  onOpen?: PortOnOpen;
686
705
  visibility?: PortVisibility;
706
+ description?: string;
707
+ name?: string;
687
708
  }
688
709
  export namespace PortConfig {
689
710
  export function is(config: any): config is PortConfig {
@@ -794,15 +815,14 @@ export namespace WithSnapshot {
794
815
  }
795
816
  }
796
817
 
797
- export interface WithPrebuild {
798
- snapshotBucketId: string;
818
+ export interface WithPrebuild extends WithSnapshot {
799
819
  prebuildWorkspaceId: string;
800
820
  wasPrebuilt: true;
801
821
  }
802
822
  export namespace WithPrebuild {
803
823
  export function is(context: any): context is WithPrebuild {
804
824
  return context
805
- && 'snapshotBucketId' in context
825
+ && WithSnapshot.is(context)
806
826
  && 'prebuildWorkspaceId' in context
807
827
  && 'wasPrebuilt' in context;
808
828
  }
@@ -871,8 +891,20 @@ export namespace PrebuiltWorkspaceContext {
871
891
  }
872
892
  }
873
893
 
894
+ export interface WithReferrerContext extends WorkspaceContext {
895
+ referrer: string
896
+ referrerIde?: string
897
+ }
898
+
899
+ export namespace WithReferrerContext {
900
+ export function is(context: any): context is WithReferrerContext {
901
+ return context
902
+ && 'referrer' in context;
903
+ }
904
+ }
905
+
874
906
  export interface WithEnvvarsContext extends WorkspaceContext {
875
- envvars: UserEnvVarValue[];
907
+ envvars: EnvVarWithValue[];
876
908
  }
877
909
 
878
910
  export namespace WithEnvvarsContext {
@@ -1138,6 +1170,8 @@ export interface AuthProviderEntry {
1138
1170
  readonly status: AuthProviderEntry.Status;
1139
1171
 
1140
1172
  readonly oauth: OAuth2Config;
1173
+ /** A random string that is to change whenever oauth changes (enforced on DB level) */
1174
+ readonly oauthRevision?: string;
1141
1175
  }
1142
1176
 
1143
1177
  export interface OAuth2Config {
@@ -1170,39 +1204,6 @@ export namespace AuthProviderEntry {
1170
1204
  }
1171
1205
  }
1172
1206
 
1173
- export interface Branding {
1174
- readonly name: string;
1175
- readonly favicon?: string;
1176
- /** Either including domain OR absolute path (interpreted relative to host URL) */
1177
- readonly logo: string;
1178
- readonly startupLogo: string;
1179
- readonly showProductivityTips: boolean;
1180
- readonly redirectUrlIfNotAuthenticated?: string;
1181
- readonly redirectUrlAfterLogout?: string;
1182
- readonly homepage: string;
1183
- readonly ide?: {
1184
- readonly logo: string;
1185
- readonly showReleaseNotes: boolean;
1186
- readonly helpMenu: Branding.Link[];
1187
- }
1188
- readonly links: {
1189
- readonly header: Branding.Link[];
1190
- readonly footer: Branding.Link[];
1191
- readonly social: Branding.SocialLink[];
1192
- readonly legal: Branding.Link[];
1193
- }
1194
- }
1195
- export namespace Branding {
1196
- export interface Link {
1197
- readonly name: string;
1198
- readonly url: string;
1199
- }
1200
- export interface SocialLink {
1201
- readonly type: string;
1202
- readonly url: string;
1203
- }
1204
- }
1205
-
1206
1207
  export interface Configuration {
1207
1208
  readonly daysBeforeGarbageCollection: number;
1208
1209
  readonly garbageCollectionStartDate: number;
@@ -6,11 +6,16 @@
6
6
 
7
7
  import { PrebuiltWorkspaceState } from "./protocol";
8
8
  import { v4 as uuidv4 } from 'uuid';
9
+ import { DeepPartial } from "./util/deep-partial";
9
10
 
10
11
  export interface ProjectConfig {
11
12
  '.gitpod.yml': string;
12
13
  }
13
14
 
15
+ export interface ProjectSettings {
16
+ useIncrementalPrebuilds?: boolean;
17
+ }
18
+
14
19
  export interface Project {
15
20
  id: string;
16
21
  name: string;
@@ -20,6 +25,7 @@ export interface Project {
20
25
  userId?: string;
21
26
  appInstallationId: string;
22
27
  config?: ProjectConfig;
28
+ settings?: ProjectSettings;
23
29
  creationTime: string;
24
30
  /** This is a flag that triggers the HARD DELETION of this entity */
25
31
  deleted?: boolean;
@@ -36,7 +42,13 @@ export namespace Project {
36
42
  }
37
43
 
38
44
  export interface Overview {
39
- branches: BranchDetails[]
45
+ branches: BranchDetails[];
46
+ }
47
+
48
+ export namespace Overview {
49
+ export function is(data?: any): data is Project.Overview {
50
+ return Array.isArray(data?.branches);
51
+ }
40
52
  }
41
53
 
42
54
  export interface BranchDetails {
@@ -55,6 +67,8 @@ export namespace Project {
55
67
  }
56
68
  }
57
69
 
70
+ export type PartialProject = DeepPartial<Project> & Pick<Project, 'id'>;
71
+
58
72
  export interface PrebuildWithStatus {
59
73
  info: PrebuildInfo;
60
74
  status: PrebuiltWorkspaceState;
@@ -64,6 +78,7 @@ export interface PrebuildWithStatus {
64
78
  export interface PrebuildInfo {
65
79
  id: string;
66
80
  buildWorkspaceId: string;
81
+ basedOnPrebuildId?: string;
67
82
 
68
83
  teamId?: string;
69
84
  userId?: string;
@@ -30,7 +30,13 @@ class SegmentAnalyticsWriter implements IAnalyticsWriter {
30
30
 
31
31
  identify(msg: IdentifyMessage) {
32
32
  try {
33
- this.analytics.identify(msg, (err: Error) => {
33
+ this.analytics.identify({
34
+ ...msg,
35
+ integrations: {
36
+ "All": true,
37
+ "Mixpanel": !!msg.userId
38
+ }
39
+ }, (err: Error) => {
34
40
  if (err) {
35
41
  log.warn("analytics.identify failed", err);
36
42
  }
@@ -42,7 +48,13 @@ class SegmentAnalyticsWriter implements IAnalyticsWriter {
42
48
 
43
49
  track(msg: TrackMessage) {
44
50
  try {
45
- this.analytics.track(msg, (err: Error) => {
51
+ this.analytics.track({
52
+ ...msg,
53
+ integrations: {
54
+ "All": true,
55
+ "Mixpanel": !!msg.userId
56
+ }
57
+ }, (err: Error) => {
46
58
  if (err) {
47
59
  log.warn("analytics.track failed", err);
48
60
  }
@@ -54,7 +66,13 @@ class SegmentAnalyticsWriter implements IAnalyticsWriter {
54
66
 
55
67
  page(msg: PageMessage) {
56
68
  try{
57
- this.analytics.page(msg, (err: Error) => {
69
+ this.analytics.page({
70
+ ...msg,
71
+ integrations: {
72
+ "All": true,
73
+ "Mixpanel": !!msg.userId
74
+ }
75
+ }, (err: Error) => {
58
76
  if (err) {
59
77
  log.warn("analytics.page failed", err);
60
78
  }
@@ -4,6 +4,8 @@
4
4
  * See License-AGPL.txt in the project root for license information.
5
5
  */
6
6
 
7
+ import { repeat } from "./repeat";
8
+
7
9
 
8
10
  interface CacheEntry<T> {
9
11
  key: string;
@@ -41,8 +43,12 @@ export class GarbageCollectedCache<T> {
41
43
  return entry.value;
42
44
  }
43
45
 
46
+ public delete(key: string) {
47
+ this.store.delete(key);
48
+ }
49
+
44
50
  protected regularlyCollectGarbage() {
45
- setInterval(() => this.collectGarbage(), this.gcIntervalSeconds * 1000);
51
+ repeat(() => this.collectGarbage(), this.gcIntervalSeconds * 1000);
46
52
  }
47
53
 
48
54
  protected collectGarbage() {
@@ -27,5 +27,22 @@ const expect = chai.expect
27
27
  expect(longestName.length <= 36, `"${longestName}" is longer than 36 chars (${longestName.length})`).to.be.true;
28
28
  }
29
29
 
30
+ @test public async testCustomName() {
31
+ const data = [
32
+ ['foo','bar','foo-bar-'],
33
+ ['f','bar','.{2,16}-bar-'],
34
+ ['gitpod-io','gitpod','gitpodio-gitpod-'],
35
+ ['this is rather long and has some "§$"% special chars','also here pretty long and needs abbreviation','thisisratherlon-alsohere-'],
36
+ ['breatheco-de', 'python-flask-api-tutorial', 'breathecode-pythonflaska-'],
37
+ ['UPPER', "CaSe", "upper-case-"]
38
+ ]
39
+ for (const d of data) {
40
+ const id = await generateWorkspaceID(d[0], d[1]);
41
+ expect(id).match(new RegExp("^"+d[2]));
42
+ expect(new GitpodHostUrl().withWorkspacePrefix(id, "eu").workspaceId).to.equal(id);
43
+ expect(id.length <= 36, `"${id}" is longer than 36 chars (${id.length})`).to.be.true;
44
+ }
45
+ }
46
+
30
47
  }
31
48
  module.exports = new TestGenerateWorkspaceId()
@@ -5,8 +5,26 @@
5
5
  */
6
6
  import randomNumber = require("random-number-csprng");
7
7
 
8
- export async function generateWorkspaceID(): Promise<string> {
9
- return (await random(colors))+'-'+(await random(animals))+'-'+(await random(characters, 8));
8
+ export async function generateWorkspaceID(firstSegment?: string, secondSegment?: string): Promise<string> {
9
+ const firstSeg = clean(firstSegment) || await random(colors);
10
+ const secSeg = clean(secondSegment, Math.min(15, 23 - firstSeg.length)) || await random(animals);
11
+ return firstSeg+'-'+secSeg+'-'+(await random(characters, 11));
12
+ }
13
+
14
+ function clean(segment: string | undefined, maxChars: number = 15) {
15
+ if (!segment) {
16
+ return undefined;
17
+ }
18
+ segment = segment.toLowerCase();
19
+ let result = '';
20
+ for (let i =0; i < segment.length; i++) {
21
+ if (characters.indexOf(segment[i]) !== -1) {
22
+ result += segment[i];
23
+ }
24
+ }
25
+ if (result.length >= 2) {
26
+ return result.substring(0, maxChars);
27
+ }
10
28
  }
11
29
 
12
30
  async function random(array: string[], length: number = 1): Promise<string> {
@@ -12,13 +12,13 @@ export interface UrlChange {
12
12
  }
13
13
  export type UrlUpdate = UrlChange | Partial<URL>;
14
14
 
15
- const basewoWkspaceIDRegex = "(([a-f][0-9a-f]{7}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})|([0-9a-z]{2,16}-[0-9a-z]{2,16}-[0-9a-z]{8}))";
15
+ const baseWorkspaceIDRegex = "(([a-f][0-9a-f]{7}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})|([0-9a-z]{2,16}-[0-9a-z]{2,16}-[0-9a-z]{8,11}))";
16
16
 
17
17
  // this pattern matches v4 UUIDs as well as the new generated workspace ids (e.g. pink-panda-ns35kd21)
18
- const workspaceIDRegex = RegExp(`^${basewoWkspaceIDRegex}$`);
18
+ const workspaceIDRegex = RegExp(`^${baseWorkspaceIDRegex}$`);
19
19
 
20
20
  // this pattern matches URL prefixes of workspaces
21
- const workspaceUrlPrefixRegex = RegExp(`^([0-9]{4,6}-)?${basewoWkspaceIDRegex}\\.`);
21
+ const workspaceUrlPrefixRegex = RegExp(`^([0-9]{4,6}-)?${baseWorkspaceIDRegex}\\.`);
22
22
 
23
23
  export class GitpodHostUrl {
24
24
  readonly url: URL;
@@ -108,10 +108,6 @@ export class GitpodHostUrl {
108
108
  return this.with(url => ({ pathname: '/preferences' }));
109
109
  }
110
110
 
111
- asGraphQLApi(): GitpodHostUrl {
112
- return this.with(url => ({ pathname: '/graphql/' }));
113
- }
114
-
115
111
  asStart(workspaceId = this.workspaceId): GitpodHostUrl {
116
112
  return this.withoutWorkspacePrefix().with({
117
113
  pathname: '/start/',
@@ -154,7 +150,7 @@ export class GitpodHostUrl {
154
150
  return undefined;
155
151
  }
156
152
 
157
- get blobServe(): boolean {
153
+ get blobServe(): boolean {
158
154
  const hostSegments = this.url.host.split(".");
159
155
  if (hostSegments[0] === 'blobserve') {
160
156
  return true;
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Copyright (c) 2020 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 { opentracing } from "jaeger-client";
8
+
9
+ // Type definitions for jaeger-client which are not exported by @types/jaeger-client
10
+ // Project: https://github.com/uber/jaeger-client-node
11
+ // Definitions by: Julian Steger <https://github.com/julianste>
12
+ // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
13
+
14
+ export interface TracingConfig {
15
+ serviceName?: string;
16
+ disable?: boolean;
17
+ sampler?: SamplerConfig;
18
+ reporter?: ReporterConfig;
19
+ }
20
+
21
+ export interface TracingOptions {
22
+ reporter?: Reporter;
23
+ metrics?: MetricsFactory;
24
+ logger?: Logger;
25
+ tags?: any;
26
+ }
27
+
28
+ export interface ReporterConfig {
29
+ logSpans?: boolean;
30
+ agentHost?: string;
31
+ agentPort?: number;
32
+ flushIntervalMs?: number;
33
+ }
34
+
35
+ export interface SamplerConfig {
36
+ type: string;
37
+ param: number;
38
+ host?: string;
39
+ port?: number;
40
+ refreshIntervalMs?: number;
41
+ }
42
+
43
+ export interface Logger {
44
+ info(msg: string): void;
45
+ error(msg: string): void;
46
+ }
47
+
48
+ export interface Reporter {
49
+ report(span: opentracing.Span): void;
50
+ close(callback?: () => void): void;
51
+ setProcess(serviceName: string, tags: any): void;
52
+ }
53
+
54
+ export interface MetricsFactory {
55
+ createCounter(name: string, tags: any): Counter;
56
+ createTimer(name: string, tags: any): Timer;
57
+ createGauge(name: string, tags: any): Gauge;
58
+ }
59
+
60
+ // Counter tracks the number of times an event has occurred
61
+ export interface Counter {
62
+ // Adds the given value to the counter.
63
+ increment(delta: number): void;
64
+ }
65
+
66
+ // Timer tracks how long an operation took and also computes percentiles.
67
+ export interface Timer {
68
+ // Records the time passed in.
69
+ record(value: number): void;
70
+ }
71
+
72
+ // Gauge returns instantaneous measurements of something as an int64 value
73
+ export interface Gauge {
74
+ // Update the gauge to the value passed in.
75
+ update(value: number): void;
76
+ }
77
+
78
+ // export function initTracer(
79
+ // tracingConfig: TracingConfig,
80
+ // tracingOptions: TracingOptions,
81
+ // ): opentracing.Tracer;
82
+
83
+ // export function initTracerFromEnv(
84
+ // tracingConfig: TracingConfig,
85
+ // tracingOptions: TracingOptions,
86
+ // ): opentracing.Tracer;
87
+
88
+ export interface SamplingDecision {
89
+ sample: boolean;
90
+ retryable: boolean;
91
+ tags: any;
92
+ }
93
+
94
+ // added by TypeFox
95
+ export interface Sampler {
96
+ name(): string
97
+ isSampled(operation: string, tags: any): boolean;
98
+ onCreateSpan(span: opentracing.Span): SamplingDecision;
99
+ onSetOperationName(span: opentracing.Span, operationName: string): SamplingDecision;
100
+ onSetTag(span: opentracing.Span, key: string, value: any): SamplingDecision;
101
+ close(callback: () => void): void
102
+ }
@@ -4,7 +4,7 @@
4
4
  * See License-AGPL.txt in the project root for license information.
5
5
  */
6
6
 
7
- const REGEX_WORKSPACE_ID = /[0-9a-z]{2,16}-[0-9a-z]{2,16}-[0-9a-z]{8}/;
7
+ const REGEX_WORKSPACE_ID = /[0-9a-z]{2,16}-[0-9a-z]{2,16}-[0-9a-z]{8,11}/;
8
8
  const REGEX_WORKSPACE_ID_EXACT = new RegExp(`^${REGEX_WORKSPACE_ID.source}$`);
9
9
  // We need to parse the workspace id precisely here to get the case '<some-str>-<port>-<wsid>.ws.' right
10
10
  const REGEX_WORKSPACE_ID_FROM_HOSTNAME = new RegExp(`(${REGEX_WORKSPACE_ID.source})\.ws`);
@@ -0,0 +1,45 @@
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 { Disposable } from "..";
8
+ import { log } from "./logging";
9
+
10
+ /**
11
+ * This intends to be a drop-in replacement for 'setInterval' implemented with a 'setTimeout' chain
12
+ * to ensure we're not creating more timeouts than we can process.
13
+ * @param op
14
+ * @param everyMilliseconds
15
+ * @returns
16
+ */
17
+ export function repeat(op: () => Promise<void> | void, everyMilliseconds: number): Disposable {
18
+ let timer: NodeJS.Timeout | undefined = undefined;
19
+ let stopped = false;
20
+ const repeated = () => {
21
+ if (stopped) {
22
+ // in case we missed the clearTimeout i 'await'
23
+ return;
24
+ }
25
+
26
+ timer = setTimeout(async () => {
27
+ try {
28
+ await op();
29
+ } catch (err) {
30
+ // catch error here to
31
+ log.error(err);
32
+ }
33
+
34
+ repeated(); // chain ourselves - after the 'await'
35
+ }, everyMilliseconds);
36
+ };
37
+ repeated();
38
+
39
+ return Disposable.create(() => {
40
+ stopped = true;
41
+ if (timer) {
42
+ clearTimeout(timer);
43
+ }
44
+ });
45
+ }
@@ -0,0 +1,83 @@
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 { suite, test } from "mocha-typescript"
8
+ import * as chai from "chai"
9
+ import { TraceContext } from "./tracing";
10
+ import { MockTracer } from "opentracing";
11
+
12
+ const expect = chai.expect
13
+
14
+ @suite class TestTracing {
15
+
16
+ @test public async testTracingContext_addNestedTags() {
17
+ const tracer = new MockTracer();
18
+ const span = tracer.startSpan('testTracingContext_addNestedTags');
19
+ TraceContext.addNestedTags({ span }, {
20
+ rpc: {
21
+ system: "jsonrpc",
22
+ jsonrpc: {
23
+ version: "1.0",
24
+ method: "test",
25
+ parameters: ["abc", "def"],
26
+ },
27
+ },
28
+ });
29
+
30
+ const mockSpan = tracer.report().spans[0];
31
+ expect(mockSpan.tags()).to.deep.equal({
32
+ "rpc.system": "jsonrpc",
33
+ "rpc.jsonrpc.version": "1.0",
34
+ "rpc.jsonrpc.method": "test",
35
+ "rpc.jsonrpc.parameters.0": "abc",
36
+ "rpc.jsonrpc.parameters.1": "def",
37
+ });
38
+ }
39
+
40
+ @test public async testTracingContext_addNestedTags_null() {
41
+ const tracer = new MockTracer();
42
+ const span = tracer.startSpan('testTracingContext_addNestedTags_null');
43
+ TraceContext.addNestedTags({ span }, {
44
+ someShape: {
45
+ thisIsNull: null,
46
+ thisIsUndefined: undefined,
47
+ },
48
+ });
49
+
50
+ const mockSpan = tracer.report().spans[0];
51
+ expect(mockSpan.tags()).to.deep.equal({
52
+ "someShape.thisIsNull": null,
53
+ "someShape.thisIsUndefined": undefined,
54
+ });
55
+ }
56
+
57
+ @test public async testTracingContext_addJsonRPCParameters() {
58
+ const tracer = new MockTracer();
59
+ const span = tracer.startSpan('testTracingContext_addJsonRPCParameters');
60
+ const ctx = { span };
61
+ TraceContext.addJsonRPCParameters(ctx, {
62
+ one: "one",
63
+ two: {
64
+ name: "two",
65
+ some: "shape",
66
+ containing: "PII",
67
+ },
68
+ three: "three",
69
+ });
70
+
71
+ const mockSpan = tracer.report().spans[0];
72
+ expect(mockSpan.tags()).to.deep.equal({
73
+ "rpc.jsonrpc.parameters.one": "one",
74
+ "rpc.jsonrpc.parameters.two.containing": "PII",
75
+ "rpc.jsonrpc.parameters.two.name": "two",
76
+ "rpc.jsonrpc.parameters.two.some": "shape",
77
+ "rpc.jsonrpc.parameters.three": "three",
78
+ "rpc.system": "jsonrpc",
79
+ });
80
+ }
81
+
82
+ }
83
+ module.exports = new TestTracing()