Skip to content

Commit 17ce731

Browse files
mrubenscteroomotejr
authored
Prototype of a Roomote tab (#147)
Co-authored-by: cte <[email protected]> Co-authored-by: Roomote <[email protected]> Co-authored-by: John Richmond <[email protected]>
1 parent 7dcdf60 commit 17ce731

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+3503
-574
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,4 @@ Thumbs.db
2626
*.log
2727

2828
# project mcp config
29-
.roo/mcp.json
29+
.roo/mcp.json

.roo/rules/rules.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
## Testing & Formatting
44

55
- **Test**: `pnpm test` (runs all tests via Turbo)
6-
- **Test single file**: `pnpm test path/to/file.test.ts`
76
- **Lint**: `pnpm lint` (ESLint with TypeScript support)
87
- **Type check**: `pnpm check-types`
98
- **Format**: Files are auto-formatted on commit via lint-staged

apps/roomote/package.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
"controller:production": "dotenvx run -f ../../.env.production -- tsx src/lib/controller.ts",
1414
"worker": "dotenvx run -f ../../.env.development -- tsx src/lib/worker.ts",
1515
"worker:production": "dotenvx run -f ../../.env.production -- tsx src/lib/worker.ts",
16-
"cli": "dotenvx run -f ../../.env.development -- tsx src/lib/cli.ts",
17-
"cli:production": "dotenvx run -f ../../.env.production -- tsx src/lib/cli.ts",
1816
"clean": "rimraf .next .turbo"
1917
},
2018
"dependencies": {
@@ -24,7 +22,6 @@
2422
"@roo-code-cloud/job-auth": "workspace:^",
2523
"@roo-code/types": "^1.30.0",
2624
"bullmq": "^5.37.0",
27-
"cmd-ts": "^0.13.0",
2825
"drizzle-orm": "^0.44.2",
2926
"execa": "^9.6.0",
3027
"ioredis": "^5.6.1",

apps/roomote/src/app/api/webhooks/github/handlers/__tests__/utils.test.ts

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ describe('GitHub Webhook Utils', () => {
8787
const mockJob = { id: 123 };
8888
const mockEnqueuedJob = { id: 'enqueued-123' };
8989
const mockCloudJobs = {};
90+
const testOrgId = 'test-org-123';
9091

9192
beforeEach(() => {
9293
mockDb.insert.mockReturnValue({
@@ -107,13 +108,14 @@ describe('GitHub Webhook Utils', () => {
107108
body: 'Test body',
108109
};
109110

110-
const result = await createAndEnqueueJob(type, payload);
111+
const result = await createAndEnqueueJob(type, payload, testOrgId);
111112

112113
expect(mockDb.insert).toHaveBeenCalledWith(mockCloudJobs);
113114
expect(mockEnqueue).toHaveBeenCalledWith({
114115
jobId: mockJob.id,
115116
type,
116117
payload,
118+
orgId: testOrgId,
117119
});
118120
expect(result).toEqual({
119121
jobId: mockJob.id,
@@ -136,9 +138,9 @@ describe('GitHub Webhook Utils', () => {
136138
body: 'Test',
137139
};
138140

139-
await expect(createAndEnqueueJob(type, payload)).rejects.toThrow(
140-
'Failed to create `cloudJobs` record.',
141-
);
141+
await expect(
142+
createAndEnqueueJob(type, payload, testOrgId),
143+
).rejects.toThrow('Failed to create `cloudJobs` record.');
142144
});
143145

144146
it('should throw error when enqueue fails to return job ID', async () => {
@@ -152,9 +154,9 @@ describe('GitHub Webhook Utils', () => {
152154
body: 'Test',
153155
};
154156

155-
await expect(createAndEnqueueJob(type, payload)).rejects.toThrow(
156-
'Failed to get enqueued job ID.',
157-
);
157+
await expect(
158+
createAndEnqueueJob(type, payload, testOrgId),
159+
).rejects.toThrow('Failed to get enqueued job ID.');
158160
});
159161

160162
it('should throw error when enqueue returns undefined', async () => {
@@ -168,9 +170,9 @@ describe('GitHub Webhook Utils', () => {
168170
body: 'Test',
169171
};
170172

171-
await expect(createAndEnqueueJob(type, payload)).rejects.toThrow(
172-
'Failed to get enqueued job ID.',
173-
);
173+
await expect(
174+
createAndEnqueueJob(type, payload, testOrgId),
175+
).rejects.toThrow('Failed to get enqueued job ID.');
174176
});
175177

176178
it('should handle different job types', async () => {
@@ -189,12 +191,13 @@ describe('GitHub Webhook Utils', () => {
189191
commentUrl: 'https://github.com/test/repo/issues/456#issuecomment-789',
190192
};
191193

192-
const result = await createAndEnqueueJob(type, payload);
194+
const result = await createAndEnqueueJob(type, payload, testOrgId);
193195

194196
expect(mockEnqueue).toHaveBeenCalledWith({
195197
jobId: mockJob.id,
196198
type,
197199
payload,
200+
orgId: testOrgId,
198201
});
199202
expect(result).toEqual({
200203
jobId: mockJob.id,
@@ -213,7 +216,7 @@ describe('GitHub Webhook Utils', () => {
213216
body: 'Test',
214217
};
215218

216-
await createAndEnqueueJob(type, payload);
219+
await createAndEnqueueJob(type, payload, testOrgId);
217220

218221
expect(consoleSpy).toHaveBeenCalledWith(
219222
`🔗 Enqueued ${type} job (id: ${mockJob.id}) ->`,
@@ -236,9 +239,9 @@ describe('GitHub Webhook Utils', () => {
236239
body: 'Test',
237240
};
238241

239-
await expect(createAndEnqueueJob(type, payload)).rejects.toThrow(
240-
'Database connection failed',
241-
);
242+
await expect(
243+
createAndEnqueueJob(type, payload, testOrgId),
244+
).rejects.toThrow('Database connection failed');
242245
});
243246

244247
it('should handle enqueue service errors', async () => {
@@ -252,9 +255,9 @@ describe('GitHub Webhook Utils', () => {
252255
body: 'Test',
253256
};
254257

255-
await expect(createAndEnqueueJob(type, payload)).rejects.toThrow(
256-
'Queue service unavailable',
257-
);
258+
await expect(
259+
createAndEnqueueJob(type, payload, testOrgId),
260+
).rejects.toThrow('Queue service unavailable');
258261
});
259262
});
260263

@@ -362,6 +365,7 @@ describe('GitHub Webhook Utils', () => {
362365
// Test job creation in a realistic webhook scenario.
363366
const mockJob = { id: 456 };
364367
const mockEnqueuedJob = { id: 'job-456' };
368+
const testOrgId = 'test-org-456';
365369

366370
mockDb.insert.mockReturnValue({
367371
values: vi.fn().mockReturnValue({
@@ -371,12 +375,16 @@ describe('GitHub Webhook Utils', () => {
371375
mockEnqueue.mockResolvedValue(mockEnqueuedJob);
372376

373377
// Create job after successful verification.
374-
const result = await createAndEnqueueJob('github.issue.fix', {
375-
repo: 'test/repo',
376-
issue: 123,
377-
title: 'Test issue',
378-
body: 'Test issue body',
379-
});
378+
const result = await createAndEnqueueJob(
379+
'github.issue.fix',
380+
{
381+
repo: 'test/repo',
382+
issue: 123,
383+
title: 'Test issue',
384+
body: 'Test issue body',
385+
},
386+
testOrgId,
387+
);
380388

381389
expect(result).toEqual({
382390
jobId: mockJob.id,

apps/roomote/src/app/api/webhooks/github/handlers/utils.ts

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import { createHmac } from 'crypto';
2+
import { or, eq } from 'drizzle-orm';
23

34
import {
45
type JobType,
56
type JobPayload,
67
db,
78
cloudJobs,
9+
orgs,
810
} from '@roo-code-cloud/db/server';
911

1012
import { enqueue } from '@/lib';
@@ -25,17 +27,38 @@ export function verifySignature(
2527
export async function createAndEnqueueJob<T extends JobType>(
2628
type: T,
2729
payload: JobPayload<T>,
30+
orgId?: string,
2831
): Promise<{ jobId: number; enqueuedJobId: string }> {
32+
// @TODO: Require `orgId` to be specified.
33+
const organizationId =
34+
orgId ||
35+
(
36+
await db
37+
.select({ id: orgs.id })
38+
.from(orgs)
39+
.where(or(eq(orgs.name, 'Roo Code'), eq(orgs.name, 'Roo Code / Dev')))
40+
.limit(1)
41+
)[0]?.id;
42+
43+
if (!organizationId) {
44+
throw new Error('Organization ID is required for job creation.');
45+
}
46+
2947
const [job] = await db
3048
.insert(cloudJobs)
31-
.values({ type, payload, status: 'pending' })
49+
.values({ type, payload, status: 'pending', orgId: organizationId })
3250
.returning();
3351

3452
if (!job) {
3553
throw new Error('Failed to create `cloudJobs` record.');
3654
}
3755

38-
const enqueuedJob = await enqueue({ jobId: job.id, type, payload });
56+
const enqueuedJob = await enqueue({
57+
jobId: job.id,
58+
type,
59+
payload,
60+
orgId: organizationId,
61+
});
3962
console.log(`🔗 Enqueued ${type} job (id: ${job.id}) ->`, payload);
4063

4164
if (!enqueuedJob.id) {

0 commit comments

Comments
 (0)