Skip to content

feat: implement webhook and event emitter#3

Draft
ricotandrio wants to merge 15 commits intomasterfrom
webhook/discord
Draft

feat: implement webhook and event emitter#3
ricotandrio wants to merge 15 commits intomasterfrom
webhook/discord

Conversation

@ricotandrio
Copy link
Copy Markdown
Owner

This pull request introduces a significant refactor of the application's core orchestration and data access layers, focusing on modularizing integrations, improving maintainability, and enhancing event handling. The changes involve moving business logic from use case files to orchestration modules, replacing direct database access with integration layers, removing legacy code, and introducing a new event bus system. Additionally, configuration and LLM (Large Language Model) handling are generalized to support multiple providers.

@ricotandrio ricotandrio requested a review from Copilot April 5, 2026 15:23
@ricotandrio ricotandrio marked this pull request as draft April 5, 2026 15:24
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR refactors the app to route GitHub/DB/LLM interactions through explicit integration modules, adds a lightweight event bus (with analytics consumer wiring), and introduces an Express endpoint to receive GitHub webhooks.

Changes:

  • Introduces integrations for GitHub, DB (SQLite), and LLM providers (Gemini/OpenAI), and migrates bot orchestration to use them.
  • Adds a new in-process event bus and an analytics consumer (console-backed).
  • Adds GitHub webhook endpoints to the API server and adds Discord assignment notification behavior.

Reviewed changes

Copilot reviewed 85 out of 94 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
tsconfig.json Minor tsconfig comment change.
src/utils/logger.ts Updates config import path.
src/utils/index.ts Re-exports logger via utils barrel.
src/main.bot.ts Wires integrations + analytics + starts bot.
src/main.api.ts Updates config import path for API entrypoint.
src/interfaces/bot/services/assignment-notification.service.ts Adds Discord channel notification helper for assignments.
src/interfaces/bot/runtime-config.ts Adds simple runtime config storage for standup channel ID.
src/interfaces/bot/handlers/message-create.handler.ts Updates logger import + handler filename conventions.
src/interfaces/bot/handlers/llm-command.handler.ts Switches from usecases to orchestrations; adds assignment notifications.
src/interfaces/bot/handlers/interaction-create.handler.ts Updates logger import.
src/interfaces/bot/handlers/index.ts Renames handler imports; registers Discord event handlers.
src/interfaces/bot/handlers/guild-create.handler.ts Updates logger import path.
src/interfaces/bot/handlers/client-ready.handler.ts Updates logger import path.
src/interfaces/bot/commands/unlink-github.command.ts Switches to orchestrations; tweaks reply message.
src/interfaces/bot/commands/status.command.ts Switches to orchestrations; updates Issue typing import.
src/interfaces/bot/commands/link-github.command.ts Switches to orchestrations.
src/interfaces/bot/commands/index.ts Updates command module filenames to kebab-case.
src/interfaces/bot/commands/create-issue.command.ts Switches to orchestrations; updates logger import.
src/interfaces/bot/commands/assign-issue.command.ts Adds ephemeral reply + assignment notifications; switches to orchestrations.
src/interfaces/bot/commands/add-repository.command.ts Switches to orchestrations.
src/interfaces/bot/client.ts Adds runtime config + DB connect (currently duplicated) before bot start.
src/interfaces/api/client.ts Adds JSON API responses + GitHub webhook endpoints with logging.
src/integrations/llm/providers/openai/openai.provider.ts Adds OpenAI provider adapter.
src/integrations/llm/providers/gemini/gemini.provider.ts Adds Gemini provider adapter.
src/integrations/llm/prompts/index.ts Exports prompt(s) for LLM integration.
src/integrations/llm/prompts/gitbot.prompt.ts Renames system prompt constant for GitBot usage.
src/integrations/llm/prompts/assistant.prompt.ts Adds a generic assistant prompt.
src/integrations/llm/llm.types.ts Defines LLMProvider interface.
src/integrations/llm/llm.integration.ts Adds LLM integration selecting provider + executing actions.
src/integrations/llm/index.ts Exports singleton llmIntegration.
src/integrations/integration.interface.ts Adds common integration interface.
src/integrations/github/repository/repository.types.ts Adds payload typing for repo listing.
src/integrations/github/repository/index.ts Exports repository actions/types.
src/integrations/github/repository/actions/get-repositories.action.ts Adds Octokit action to list repos for a user.
src/integrations/github/issue/issue.types.ts Adds payload typings for issue actions.
src/integrations/github/issue/index.ts Exports issue actions/types.
src/integrations/github/issue/actions/get-issues.action.ts Adds Octokit action to list repo issues.
src/integrations/github/issue/actions/create-issue.action.ts Adds Octokit action to create an issue.
src/integrations/github/issue/actions/assign-issue.action.ts Adds Octokit action to assign users to an issue.
src/integrations/github/index.ts Exports singleton githubIntegration.
src/integrations/github/github.types.ts Defines GitHub action names + payload map type(s).
src/integrations/github/github.integration.ts Adds GitHub integration wrapper around action dispatch.
src/integrations/github/github.client.ts Wraps Octokit client creation.
src/integrations/db/user-mappings/user-mappings.types.ts Adds DB user mapping row/payload types.
src/integrations/db/user-mappings/index.ts Exports user-mapping DB actions/types.
src/integrations/db/user-mappings/actions/set-user-mapping.action.ts Adds upsert for user mappings.
src/integrations/db/user-mappings/actions/get-user-mapping.action.ts Adds lookup for user mappings.
src/integrations/db/user-mappings/actions/delete-user-mapping.action.ts Adds delete for user mappings.
src/integrations/db/index.ts Exports DB integration surface.
src/integrations/db/guild-repositories/index.ts Exports guild-repository DB actions/types.
src/integrations/db/guild-repositories/guild-repositories.types.ts Adds DB guild repo row/payload types.
src/integrations/db/guild-repositories/actions/remove-guild-repository.action.ts Adds delete for guild repositories.
src/integrations/db/guild-repositories/actions/get-guild-repositories.action.ts Adds list for guild repositories.
src/integrations/db/guild-repositories/actions/add-guild-repository.action.ts Adds insert for guild repositories.
src/integrations/db/db.types.ts Adds DB action union type.
src/integrations/db/db.integration.ts Adds DB integration wrapper and singleton export.
src/integrations/db/db.client.ts Adds SQLite client wrapper + schema initialization.
src/integrations/analytics/providers/index.ts Exports analytics providers.
src/integrations/analytics/providers/console.provider.ts Adds console analytics provider.
src/integrations/analytics/index.ts Adds analytics service + event consumer registration.
src/integrations/analytics/analytics.types.ts Adds analytics provider interface.
src/integrations/analytics/analytics.services.ts Adds fire-and-forget analytics tracking wrapper.
src/infrastructure/llm/index.ts Removes legacy LLM export.
src/infrastructure/llm/client.ts Removes legacy Gemini client wiring.
src/infrastructure/github/services/issue.service.ts Removes legacy GitHub issue service.
src/infrastructure/github/services/index.ts Removes legacy GitHub services barrel.
src/infrastructure/github/client.ts Removes legacy GitHub client wiring.
src/infrastructure/db/repositories/DbUserMappingRepository.repository.ts Removes legacy DB repository wrapper.
src/infrastructure/db/repositories/DbGuildRepository.repository.ts Removes legacy DB repository wrapper.
src/infrastructure/db/repositories.ts Removes legacy DB helper functions.
src/infrastructure/db/index.ts Removes legacy DB exports.
src/infrastructure/db/client.ts Removes legacy DB client/init function.
src/domain/entities/Issue.ts Removes legacy domain Issue type.
src/domain/entities/index.ts Removes legacy domain entities export.
src/core/orchestrations/user.orchestration.ts Moves user mapping logic to DB integration-based orchestration.
src/core/orchestrations/repository.orchestration.ts Moves guild repo config logic to DB integration-based orchestration.
src/core/orchestrations/llm.orchestration.ts Routes LLM calls through LLM integration and DB integration.
src/core/orchestrations/issue.orchestration.ts New issue orchestration using GitHub + DB integrations and event bus.
src/core/orchestrations/index.ts Exports orchestrations as a single import surface.
src/core/events/index.ts Exports event bus + event typing and provides singleton bus.
src/core/events/events.type.ts Adds event payload typing map (analytics-focused).
src/core/events/event-bus.ts Adds in-process fire-and-forget event bus implementation.
src/config/index.ts Adds config barrel export.
src/config/env.ts Adds standup channel env + generalizes LLM provider config.
src/application/usecases/issue.usecase.ts Removes legacy issue use case implementation.
package.json Adds OpenAI SDK dependency.
package-lock.json Locks OpenAI + dependency updates.
Comments suppressed due to low confidence (3)

src/config/env.ts:26

  • config.LLM.API_KEY is always sourced from GEMINI_API_KEY, even when LLM_PROVIDER_NAME is set to openai. This makes the “multiple providers” config misleading and likely breaks OpenAI usage. Consider using a provider-agnostic env var (e.g. LLM_API_KEY) or separate keys per provider (e.g. OPENAI_API_KEY/GEMINI_API_KEY) selected based on PROVIDER_NAME.
    src/core/orchestrations/llm.orchestration.ts:5
  • config is imported but never used in this module. Removing unused imports avoids confusion and keeps the orchestration focused on its actual dependencies.
    src/core/orchestrations/llm.orchestration.ts:43
  • Log/error messages still refer to “Gemini” ('Gemini raw response', 'Gemini API error') even though the integration can be backed by OpenAI as well. Make these messages provider-agnostic (or include the provider name) to avoid confusing operational logs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

import { handleMessageCreate } from './message-create.handler';

export function registerHandlers(client: Client): void {
client.on('clientReady', handleClientReady);
Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

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

client.on('clientReady', ...) is not a Discord.js client event, so handleClientReady will never fire. Use the standard 'ready' event (and keep naming consistent with Discord.js event names).

Copilot uses AI. Check for mistakes.
Comment on lines +18 to 30
});

await llmIntegration.connect({
apiKey: config.LLM.API_KEY,
providerName: config.LLM.PROVIDER_NAME,
});

await dbIntegration.connect({ dbPath: './data/gitbot.db' });

await startBot(
config.DISCORD.BOT_TOKEN,
config.DISCORD.CLIENT_ID,
config.DISCORD.GUILD_ID,
Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

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

dbIntegration.connect() is called here and also inside startBot(), which will re-initialize/replace the singleton DB client and can lead to redundant initialization or SQLite locking issues. Connect the DB integration in one place (typically the entrypoint) and have downstream code assume it’s already connected.

Copilot uses AI. Check for mistakes.
Comment on lines +59 to 63

await deployBot(rest, CLIENT_ID, GUILD_ID);

registerHandlers(client);

Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

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

startBot() currently calls dbIntegration.connect() with a hardcoded path, but the DB is already connected in main.bot.ts. This double-connect can overwrite the existing DbClient and cause operational issues. Prefer passing a connected client (or only connecting once) and avoid hardcoding ./data/gitbot.db in this layer.

Copilot uses AI. Check for mistakes.
Comment on lines +15 to +49
function handleGithubWebhook(req: Request, res: Response): void {
const event = req.header('x-github-event');
const deliveryId = req.header('x-github-delivery');

if (!event) {
res.status(400).json({
ok: false,
error: 'Missing x-github-event header',
});
return;
}

const payload = (req.body ?? {}) as GithubWebhookPayload;

if (event === 'ping') {
logger.info({ deliveryId }, 'Received GitHub webhook ping');
res.status(200).json({ ok: true, message: 'pong' });
return;
}

logger.info(
{
event,
deliveryId,
action: payload.action,
repository: payload.repository?.full_name ?? payload.repository?.name,
sender: payload.sender?.login,
},
'Received GitHub webhook event',
);

// For now we acknowledge webhook delivery and log payload metadata.
// Domain handling can be plugged in here as use cases/events grow.
res.status(202).json({ ok: true, event });
}
Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

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

The GitHub webhook handler accepts POSTs without verifying the webhook signature (e.g. x-hub-signature-256) or otherwise authenticating the sender. This allows spoofed events and log spam. Add signature verification using a shared secret (and keep the raw body for HMAC verification via express.json({ verify }) or a raw-body middleware) before processing/acknowledging the event.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants