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
3 changes: 2 additions & 1 deletion Dockerfile.dispatcher
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ RUN --mount=type=cache,target=/root/.bun/install/cache bun install && \
# Copy source code
COPY packages/shared/ ./packages/shared/
COPY packages/dispatcher/ ./packages/dispatcher/
COPY modules/ ./modules/

# Build shared first
WORKDIR /app/packages/shared
Expand All @@ -36,4 +37,4 @@ EXPOSE 3000
# Runtime user setup is handled by node:20-alpine

# Use Node.js for runtime (better WebSocket compatibility)
CMD ["node", "dist/index.js"]
CMD ["node", "dist/packages/dispatcher/src/index.js"]
5 changes: 4 additions & 1 deletion Dockerfile.orchestrator
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ COPY packages/shared/ ./packages/shared/
COPY packages/orchestrator/src ./packages/orchestrator/src
COPY packages/orchestrator/tsconfig.json ./packages/orchestrator/
COPY packages/orchestrator/db/ ./packages/orchestrator/db/
# Copy only the module registry files, not the GitHub module (to avoid unnecessary dependencies)
COPY modules/index.ts ./modules/
COPY modules/types.ts ./modules/

# Build shared package first
WORKDIR /app/packages/shared
Expand All @@ -72,4 +75,4 @@ HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \

# Start the orchestrator with bun
WORKDIR /app/packages/orchestrator
CMD ["bun", "dist/index.js"]
CMD ["bun", "dist/packages/orchestrator/src/index.js"]
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Incorrect CMD Path in Dockerfiles

The CMD instructions in Dockerfile.orchestrator and Dockerfile.dispatcher specify an incorrect entrypoint path. The build process outputs index.js directly to the dist/ directory within each package, but the CMD expects a nested path like dist/packages/<package_name>/src/index.js. This path mismatch will cause both containers to fail on startup.

Additional Locations (2)

Fix in Cursor Fix in Web

1 change: 1 addition & 0 deletions Dockerfile.worker
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ RUN --mount=type=cache,target=/root/.bun/install/cache bun install
# Copy source code (needed for both dev and prod)
COPY packages/ ./packages/
COPY scripts/ ./scripts/
COPY modules/ ./modules/

# For production mode, build during image creation
# For dev mode, we'll build at startup to allow for live code changes
Expand Down
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ services:
NODE_ENV: production
DATABASE_URL: postgresql://postgres:${POSTGRESQL_PASSWORD:-password}@postgres:5432/peerbot?sslmode=disable
GITHUB_TOKEN: ${GITHUB_TOKEN}
ENCRYPTION_KEY: ${ENCRYPTION_KEY}
DEPLOYMENT_MODE: ${DEPLOYMENT_MODE:-docker}
DOCKER_HOST: unix:///var/run/docker.sock
CLAUDE_ALLOWED_TOOLS: ${CLAUDE_ALLOWED_TOOLS}
Expand Down
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
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
#!/usr/bin/env bun

import type { GitHubRepositoryManager } from "../github/repository-manager";
import { generateGitHubAuthUrl } from "../utils/github-utils";
import { getUserGitHubInfo } from "../slack/handlers/github-handler";
import { generateDeterministicActionId } from "./blockkit-processor";
import type { GitHubRepositoryManager } from "./repository-manager";
import { generateGitHubAuthUrl } from "./utils";
import { getUserGitHubInfo } from "./handlers";
import { createHash } from "node:crypto";
import { createLogger } from "@peerbot/shared";

const logger = createLogger("dispatcher");
const logger = createLogger("github-module");

// Inline action ID generation to avoid cross-package dependencies
function generateDeterministicActionId(
content: string,
prefix: string = "action"
): string {
const hash = createHash("sha256")
.update(content)
.digest("hex")
.substring(0, 8);
return `${prefix}_${hash}`;
}

/**
* Generate GitHub action buttons for the session branch
Expand All @@ -16,7 +28,6 @@ export async function generateGitHubActionButtons(
gitBranch: string | undefined,
hasGitChanges: boolean | undefined,
pullRequestUrl: string | undefined,
userMappings: Map<string, string>,
repoManager: GitHubRepositoryManager,
slackClient?: any
): Promise<any[] | undefined> {
Expand Down Expand Up @@ -45,11 +56,9 @@ export async function generateGitHubActionButtons(
return undefined;
}

// Get GitHub username from Slack user ID
let githubUsername = userMappings.get(userId);
if (!githubUsername && slackClient) {
// Create user mapping on-demand if not found
logger.debug(`Creating on-demand user mapping for user ${userId}`);
// Generate GitHub username from Slack user ID
let githubUsername: string;
if (slackClient) {
try {
const userInfo = await slackClient.users.info({ user: userId });
const user = userInfo.user;
Expand All @@ -66,22 +75,17 @@ export async function generateGitHubActionButtons(
.replace(/[^a-z0-9-]/g, "-")
.replace(/^-|-$/g, "");

username = `user-${username}`;
userMappings.set(userId, username);
githubUsername = username;

logger.info(`Created user mapping: ${userId} -> ${username}`);
githubUsername = `user-${username}`;
logger.debug(
`Generated GitHub username: ${userId} -> ${githubUsername}`
);
} catch (error) {
logger.error(`Failed to create user mapping for ${userId}:`, error);
const fallbackUsername = `user-${userId.substring(0, 8)}`;
userMappings.set(userId, fallbackUsername);
githubUsername = fallbackUsername;
logger.error(`Failed to get user info for ${userId}:`, error);
githubUsername = `user-${userId.substring(0, 8)}`;
}
}

if (!githubUsername) {
logger.debug(`No GitHub username mapping found for user ${userId}`);
return undefined;
} else {
// Fallback if no Slack client available
githubUsername = `user-${userId.substring(0, 8)}`;
}

// Get repository information, create if needed
Expand Down
25 changes: 25 additions & 0 deletions modules/github/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { BaseError } from "@peerbot/shared";

/**
* Error class for GitHub repository operations
*/
export class GitHubRepositoryError extends BaseError {
readonly name = "GitHubRepositoryError";

constructor(
public operation: string,
public username: string,
message: string,
cause?: Error
) {
super(message, cause);
}

toJSON(): Record<string, any> {
return {
...super.toJSON(),
operation: this.operation,
username: this.username,
};
}
}
Loading
Loading