Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion integration-tests/src/mocks/claude-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export class MockClaudeServer {
});

// Health check
this.app.get("/health", (req, res) => {
this.app.get("/health", (_req, res) => {
res.json({ status: "ok", mock: true });
});
}
Expand Down
4 changes: 2 additions & 2 deletions integration-tests/src/mocks/slack-server.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import express from "express";
import { EventEmitter } from "events";
import { EventEmitter } from "node:events";

interface SlackMessage {
ts: string;
Expand Down Expand Up @@ -97,7 +97,7 @@ export class MockSlackServer extends EventEmitter {
});

// Mock auth.test
this.app.post("/api/auth.test", (req, res) => {
this.app.post("/api/auth.test", (_req, res) => {
res.json({
ok: true,
url: "https://test-workspace.slack.com/",
Expand Down
2 changes: 1 addition & 1 deletion modules/github/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,4 +169,4 @@ export async function generateGitHubActionButtons(
// Return undefined on error - this will result in no action buttons being added
return undefined;
}
}
}
2 changes: 1 addition & 1 deletion modules/github/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ export class GitHubRepositoryError extends BaseError {
username: this.username,
};
}
}
}
2 changes: 1 addition & 1 deletion modules/github/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -433,4 +433,4 @@ export async function getUserGitHubInfo(userId: string): Promise<{
logger.error(`Failed to get GitHub info for user ${userId}:`, error);
return { token: null, username: null };
}
}
}
135 changes: 84 additions & 51 deletions modules/github/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
import { z } from 'zod';
import type { HomeTabModule, WorkerModule, OrchestratorModule, DispatcherModule, SessionContext, ActionButton, ThreadContext } from '../types';
import { GitHubRepositoryManager } from './repository-manager';
import { handleGitHubConnect, handleGitHubLogout, getUserGitHubInfo } from './handlers';
import { generateGitHubAuthUrl } from './utils';
import { z } from "zod";
import type {
HomeTabModule,
WorkerModule,
OrchestratorModule,
DispatcherModule,
SessionContext,
ActionButton,
ThreadContext,
} from "../types";
import { GitHubRepositoryManager } from "./repository-manager";
import { getUserGitHubInfo } from "./handlers";
import { generateGitHubAuthUrl } from "./utils";

// GitHub configuration schema (module-specific)
export const GitHubConfigSchema = z.object({
Expand Down Expand Up @@ -36,8 +44,10 @@ export function loadGitHubConfig(): GitHubConfig {
});
}

export class GitHubModule implements HomeTabModule, WorkerModule, OrchestratorModule, DispatcherModule {
name = 'github';
export class GitHubModule
implements HomeTabModule, WorkerModule, OrchestratorModule, DispatcherModule
{
name = "github";
private repoManager?: GitHubRepositoryManager;

isEnabled(): boolean {
Expand All @@ -46,7 +56,7 @@ export class GitHubModule implements HomeTabModule, WorkerModule, OrchestratorMo

async init(): Promise<void> {
if (!this.isEnabled()) return;

const config = loadGitHubConfig();
this.repoManager = new GitHubRepositoryManager(
config,
Expand All @@ -59,7 +69,7 @@ export class GitHubModule implements HomeTabModule, WorkerModule, OrchestratorMo

const { token, username } = await getUserGitHubInfo(userId);
const isGitHubConnected = !!token;

if (!isGitHubConnected) {
const authUrl = generateGitHubAuthUrl(userId);
return [
Expand Down Expand Up @@ -88,12 +98,18 @@ export class GitHubModule implements HomeTabModule, WorkerModule, OrchestratorMo
];
}

const userRepo = await this.repoManager.getUserRepository(username!, userId);

const userRepo = await this.repoManager.getUserRepository(
username!,
userId
);

if (userRepo) {
const repoUrl = userRepo.repositoryUrl.replace(/\.git$/, "");
const repoDisplayName = repoUrl.replace(/^https?:\/\/(www\.)?github\.com\//, "");

const repoDisplayName = repoUrl.replace(
/^https?:\/\/(www\.)?github\.com\//,
""
);

return [
{
type: "section",
Expand All @@ -109,7 +125,7 @@ export class GitHubModule implements HomeTabModule, WorkerModule, OrchestratorMo
},
];
}

return [
{
type: "section",
Expand Down Expand Up @@ -144,26 +160,24 @@ export class GitHubModule implements HomeTabModule, WorkerModule, OrchestratorMo
];
}

async handleHomeTabAction(actionId: string, userId: string, value?: any): Promise<void> {
// Home tab actions are handled by the dispatcher action handler
// This method is called from the dispatcher for module-specific actions
}

async initWorkspace(config: { repositoryUrl?: string; workspaceDir?: string }): Promise<void> {
async initWorkspace(config: {
repositoryUrl?: string;
workspaceDir?: string;
}): Promise<void> {
if (!config.repositoryUrl || !config.workspaceDir) return;

// Clone repository if not already present
const repoName = this.extractRepoName(config.repositoryUrl);
const targetDir = `${config.workspaceDir}/${repoName}`;

// Check if repo already exists
try {
const fs = await import('fs');
const fs = await import("node:fs");
if (!fs.existsSync(targetDir)) {
const { execSync } = await import('child_process');
execSync(`git clone ${config.repositoryUrl} ${targetDir}`, {
stdio: 'inherit',
cwd: config.workspaceDir
const { execSync } = await import("node:child_process");
execSync(`git clone ${config.repositoryUrl} ${targetDir}`, {
stdio: "inherit",
cwd: config.workspaceDir,
});
}
} catch (error) {
Expand Down Expand Up @@ -195,17 +209,20 @@ export class GitHubModule implements HomeTabModule, WorkerModule, OrchestratorMo
];
}

async buildEnvVars(userId: string, baseEnv: Record<string, string>): Promise<Record<string, string>> {
async buildEnvVars(
userId: string,
baseEnv: Record<string, string>
): Promise<Record<string, string>> {
const { token, username } = await getUserGitHubInfo(userId);

if (token && username) {
return {
...baseEnv,
GITHUB_TOKEN: token,
GITHUB_USER: username,
};
}

return baseEnv;
}

Expand Down Expand Up @@ -241,7 +258,7 @@ export class GitHubModule implements HomeTabModule, WorkerModule, OrchestratorMo
*/
async isGitHubCLIAuthenticated(workingDir: string): Promise<boolean> {
try {
const { execSync } = await import('child_process');
const { execSync } = await import("node:child_process");
execSync("gh auth status", {
cwd: workingDir,
stdio: "pipe",
Expand All @@ -264,7 +281,7 @@ export class GitHubModule implements HomeTabModule, WorkerModule, OrchestratorMo
return [];
}

const { generateGitHubActionButtons } = await import('./actions');
const { generateGitHubActionButtons } = await import("./actions");
const buttons = await generateGitHubActionButtons(
context.userId,
context.gitBranch,
Expand All @@ -275,38 +292,50 @@ export class GitHubModule implements HomeTabModule, WorkerModule, OrchestratorMo
context.slackClient
);

return buttons?.map(button => ({
text: button.text?.text || '',
action_id: button.action_id,
style: button.style,
value: button.value
})) || [];
return (
buttons?.map((button) => ({
text: button.text?.text || "",
action_id: button.action_id,
style: button.style,
value: button.value,
})) || []
);
}

async handleAction(actionId: string, userId: string, context: any): Promise<boolean> {
async handleAction(
actionId: string,
userId: string,
context: any
): Promise<boolean> {
// Handle GitHub-specific actions
switch (actionId) {
case "github_login":
const { handleGitHubConnect } = await import('./handlers');
case "github_login": {
const { handleGitHubConnect } = await import("./handlers");
await handleGitHubConnect(userId, context.channelId, context.client);
return true;

case "github_logout":
const { handleGitHubLogout } = await import('./handlers');
}

case "github_logout": {
const { handleGitHubLogout } = await import("./handlers");
await handleGitHubLogout(userId, context.client);
// Update home tab after logout - delegate back to action handler
if (context.updateAppHome) {
await context.updateAppHome(userId, context.client);
}
return true;

}

case "open_repository_modal":
// This is handled by repository-modal-utils which should also be moved to module
return false; // Let dispatcher handle for now

default:
// Check if it's a GitHub-specific action (prefixed with github_ or contains repo operations)
if (actionId.startsWith('github_') || actionId.includes('pr_') || actionId.includes('view_pr_')) {
if (
actionId.startsWith("github_") ||
actionId.includes("pr_") ||
actionId.includes("view_pr_")
) {
// This is a GitHub action but not one we handle directly
return false;
}
Expand All @@ -317,9 +346,13 @@ export class GitHubModule implements HomeTabModule, WorkerModule, OrchestratorMo
getRepositoryManager(): GitHubRepositoryManager | undefined {
return this.repoManager;
}

async getUserInfo(userId: string) {
return getUserGitHubInfo(userId);
}
}

export * from './repository-manager';
export * from './handlers';
export * from './utils';
export * from './errors';
export * from "./repository-manager";
export * from "./handlers";
export * from "./utils";
export * from "./errors";
6 changes: 3 additions & 3 deletions modules/github/repository-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ const logger = createLogger("github-module");

// Import from shared package and local module
import { getDbPool } from "@peerbot/shared";
import { GitHubRepositoryError } from './errors';
import type { GitHubConfig } from './index';
import { GitHubRepositoryError } from "./errors";
import type { GitHubConfig } from "./index";

export interface GitHubModuleConfig extends GitHubConfig {
// All config is already in the base GitHubConfig type
Expand Down Expand Up @@ -316,4 +316,4 @@ export class GitHubRepositoryManager {
return null;
}
}
}
}
2 changes: 1 addition & 1 deletion modules/github/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
export function generateGitHubAuthUrl(userId: string): string {
const baseUrl = process.env.INGRESS_URL || "http://localhost:8080";
return `${baseUrl}/api/github/oauth/authorize?user_id=${userId}`;
}
}
Loading
Loading