Skip to content

Commit c1d1827

Browse files
Workspace orchestration (#41)
* chore: Displaced Github APIs * feat: Updated package.json for websocket connections * feat: Added API Layer for Gitpod API Connection * feat: Added Workspace and Update Models * feat: Added Workspace Manager Service * feat: Added Gitpod Dashboard * Updated Gitpod Menu Bar * fix: Removed Gitpod PAT
1 parent ca59037 commit c1d1827

17 files changed

+5193
-97
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
# dependencies
44
/node_modules
5+
/Packages
56

67
# misc
78
.DS_Store

assets/logo-mark.svg

Lines changed: 2 additions & 1 deletion
Loading

constants.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import { Color } from "@raycast/api";
22

3-
export enum workspaceStatus {
4-
workspace_Inactive = "stopped",
5-
workspace_active = "running",
6-
workspace_progressing = "progressing",
7-
workspace_failed = "failed",
3+
export interface workspaceStatus {
4+
workspace_Inactive : "PHASE_STOPPED",
5+
workspace_active : "PHASE_RUNNING",
6+
workspace_progressing : "PHASE_CREATED" | "PHASE_INITIALIZING" | "PHASE_STOPPING" | "PHASE_PENDING"
87
}
98

109
export enum branchStatus {

package-lock.json

Lines changed: 4540 additions & 84 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,17 +123,45 @@
123123
"template"
124124
]
125125
},
126+
{
127+
"name": "gitpod_dashboard",
128+
"title": "List Gitpod Workspaces",
129+
"subtitle": "List Workspaces",
130+
"description": "List All Workspaces on your gitpod Dashboard",
131+
"mode": "view",
132+
"preferences": [
133+
{
134+
"name" : "cookie_token",
135+
"title": "Gitpod Session Cookie",
136+
"placeholder": "Only for Gitpod Beta Testers",
137+
"description": "Enter Gitpod Session Cookie from Browser",
138+
"type": "password",
139+
"required": true
140+
}
141+
]
142+
},
126143
{
127144
"name": "menubar",
128145
"title": "Recent Repositories",
129146
"subtitle": "Gitpod (Beta)",
130147
"description": "A Menubar Icon for faster access to recently visited Repositories",
148+
"interval": "10s",
131149
"mode": "menu-bar",
132150
"keywords": [
133151
"gitpod",
134152
"gp",
135153
"recent repositories",
136154
"menubar"
155+
],
156+
"preferences": [
157+
{
158+
"name" : "cookie_token",
159+
"title": "Gitpod Session Cookie",
160+
"placeholder": "Only for Gitpod Beta Testers",
161+
"description": "Enter Gitpod Session Cookie from Browser",
162+
"type": "password",
163+
"required": false
164+
}
137165
]
138166
}
139167
],
@@ -147,7 +175,8 @@
147175
"graphql-request": "^5.1.0",
148176
"lodash": "^4.17.21",
149177
"node-fetch": "^3.3.0",
150-
"octokit": "^2.0.10"
178+
"octokit": "^2.0.10",
179+
"ws": "^8.11.0"
151180
},
152181
"devDependencies": {
153182
"@types/lodash": "^4.14.191",
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
import fetch from 'node-fetch';
2+
3+
import { GitpodAPI, StartWorkspace, StopWorkspace } from "../api";
4+
5+
import { GitpodDataModel } from "./Model";
6+
7+
type IWorkspaceParams = {
8+
workspaceID: string;
9+
};
10+
11+
const workspaceURLs = {
12+
getWorkspace: "https://api.gitpod.io/gitpod.experimental.v1.WorkspacesService/GetWorkspace",
13+
getAllWorkspaces: "https://api.gitpod.io/gitpod.experimental.v1.WorkspacesService/ListWorkspaces",
14+
deleteWorkspace: "https://api.gitpod.io/gitpod.experimental.v1.WorkspacesService/DeleteWorkspace",
15+
};
16+
17+
export class IWorkspace implements GitpodDataModel {
18+
private token = "";
19+
private initialized = false;
20+
private workspaceId: string;
21+
private ownerId: string;
22+
private projectId: string;
23+
private context: {
24+
contextURL: string;
25+
git: {
26+
normalizedContextUrl: string;
27+
};
28+
};
29+
private description: string;
30+
public instanceId: string;
31+
public createdAt: string
32+
private status: {
33+
phase: string;
34+
};
35+
36+
setStatus(status : { phase: string }): IWorkspace {
37+
this.status = status;
38+
return this;
39+
}
40+
41+
getWorkspaceId(): string {
42+
if (!this.initialized) {
43+
throw new Error("IWorkspace instance not initialized");
44+
}
45+
return this.workspaceId;
46+
}
47+
48+
getOwnerId(): string {
49+
if (!this.initialized) {
50+
throw new Error("IWorkspace instance not initialized");
51+
}
52+
return this.ownerId;
53+
}
54+
55+
getProjectId(): string {
56+
if (!this.initialized) {
57+
throw new Error("IWorkspace instance not initialized");
58+
}
59+
return this.projectId;
60+
}
61+
62+
getContext(): { contextURL: string; git: { normalizedContextUrl: string } } {
63+
if (!this.initialized) {
64+
throw new Error("IWorkspace instance not initialized");
65+
}
66+
return this.context;
67+
}
68+
69+
getDescription(): string {
70+
if (!this.initialized) {
71+
throw new Error("IWorkspace instance not initialized");
72+
}
73+
return this.description;
74+
}
75+
76+
getStatus(): { phase: string } {
77+
if (!this.initialized) {
78+
throw new Error("IWorkspace instance not initialized");
79+
}
80+
return this.status;
81+
}
82+
83+
constructor(workspace: any, token: string) {
84+
this.workspaceId = workspace.workspaceId;
85+
this.ownerId = workspace.ownerId;
86+
this.projectId = workspace.projectId;
87+
this.context = workspace.context;
88+
this.status = workspace.status.instance.status;
89+
this.description = workspace.description;
90+
this.token = token;
91+
this.instanceId = workspace.status.instance.instanceId
92+
this.initialized = true;
93+
this.createdAt = workspace.status.instance.createdAt
94+
}
95+
96+
parse(json: string): IWorkspace {
97+
const data = JSON.parse(json);
98+
this.workspaceId = data.result.workspaceId;
99+
this.ownerId = data.result.ownerId;
100+
this.projectId = data.result.context.git.normalizedContextUrl.split("/").slice(-2)[0];
101+
this.context = {
102+
contextURL: data.result.context.contextUrl,
103+
git: {
104+
normalizedContextUrl: data.result.context.git.normalizedContextUrl,
105+
},
106+
};
107+
108+
this.instanceId = data.result.status.instance.instanceId
109+
this.description = data.result.description;
110+
this.status = {
111+
phase: data.result.status.instance.status.phase,
112+
};
113+
114+
this.createdAt = data.result.status.instance.createdAt
115+
116+
return this;
117+
}
118+
119+
dispose(): void {
120+
// Clear all properties
121+
this.workspaceId = "";
122+
this.ownerId = "";
123+
this.projectId = "";
124+
this.context = { contextURL: "", git: { normalizedContextUrl: "" } };
125+
this.description = "";
126+
this.status = { phase: "" };
127+
}
128+
129+
public start (api: GitpodAPI) {
130+
const workspaceParam: StartWorkspace = {
131+
method: "startWorkspace",
132+
params: this.workspaceId
133+
}
134+
135+
api.execute(workspaceParam)
136+
}
137+
138+
public fetch: (params: IWorkspaceParams) => Promise<IWorkspace> = async (
139+
params: IWorkspaceParams
140+
): Promise<IWorkspace> => {
141+
const { workspaceID } = params;
142+
143+
const response = await fetch(workspaceURLs.getWorkspace, {
144+
method: "GET",
145+
headers: {
146+
"content-type": "application/json",
147+
// Authorization: `Bearer ${this.token}`,
148+
"cookie" : `_gitpod_io_v2_=${this.token}`,
149+
},
150+
body: JSON.stringify({ workspaceID }),
151+
});
152+
const json = await response.json();
153+
154+
const workspace = this.parse(JSON.stringify(json));
155+
return workspace;
156+
};
157+
158+
public static fetchAll = async (token: string): Promise<Map<string, IWorkspace>> => {
159+
const response = await fetch(workspaceURLs.getAllWorkspaces, {
160+
method: "POST",
161+
headers: {
162+
"content-type": "application/json",
163+
// Authorization: `Bearer ${token}`,
164+
"cookie" : `_gitpod_io_v2_=${token}`
165+
},
166+
body: JSON.stringify({}),
167+
})
168+
169+
const json = await response.json() as any ;
170+
const workspaceMap = new Map<string, IWorkspace>();
171+
172+
json.result.map((workspace: any) => {
173+
const space = new IWorkspace(workspace, token);
174+
workspaceMap.set(space.workspaceId, space);
175+
})
176+
177+
return workspaceMap
178+
}
179+
180+
public delete = async () => {
181+
const response = await fetch(workspaceURLs.deleteWorkspace, {
182+
method: "GET",
183+
headers: {
184+
"Content-Type": "application/json",
185+
// Authorization: `Bearer ${this.token}`,
186+
"cookie" : `_gitpod_io_v2_=${this.token}`
187+
},
188+
body: JSON.stringify({ workspaceId: this.workspaceId }),
189+
});
190+
const result = await response.json();
191+
if (response.status !== 200) {
192+
// throw new Error(`Failed to delete workspace: ${result.message}`);
193+
}
194+
195+
this.dispose();
196+
};
197+
198+
async stop(api: GitpodAPI): Promise<void> {
199+
const workspaceParam: StopWorkspace = {
200+
201+
method: "stopWorkspace",
202+
params: this.workspaceId
203+
}
204+
205+
api.execute(workspaceParam)
206+
}
207+
}

0 commit comments

Comments
 (0)