Skip to content

refactor!: support nested event handler dirs with inferred event typing - #28

Merged
calebephrem merged 2 commits into
open-devhub:mainfrom
calebephrem:main
Aug 6, 2026
Merged

refactor!: support nested event handler dirs with inferred event typing#28
calebephrem merged 2 commits into
open-devhub:mainfrom
calebephrem:main

Conversation

@calebephrem

Copy link
Copy Markdown
Member

No description provided.

@devhub-bot devhub-bot Bot added the refactor code restructure label Aug 6, 2026
@vercel

vercel Bot commented Aug 6, 2026

Copy link
Copy Markdown

@calebephrem is attempting to deploy a commit to the Caleb's Projects Team on Vercel.

A member of the Team first needs to authorize it.

@beetle-ai

beetle-ai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Summary by Beetle

This PR implements a major architectural refactoring that transforms the event handler system from a flat, event-type-based directory structure to a nested, feature-based directory structure with inferred event typing. The key innovation is introducing a defineEventHandler() utility that enables:

  1. Nested event handler directories - Handlers can now be organized by feature (e.g., cleanup/, commands/, labeling/, standards/, linting/) rather than by event type
  2. Inferred event typing - Event handlers explicitly declare which events they handle via a events array, enabling TypeScript to infer proper types
  3. Recursive handler discovery - The main entry point now recursively scans all subdirectories to find handlers, eliminating the need for flat event-type directories
  4. Improved code organization - Related functionality is grouped together logically, making the codebase more maintainable and scalable
    This is a breaking change (indicated by the ! in the commit message) that fundamentally changes how event handlers are structured and discovered.

📁 File Changes Summary (Consolidated across all commits):

File Status Changes Description
.zed/settings.json Added +22/-0 Zed editor configuration for TypeScript/JavaScript development with JSDoc completion and code formatting settings
src/lib/eventHandler.ts Added +8/-0 New utility function defineEventHandler() that provides type-safe wrapper for event handler modules with generic event typing
src/types/eventHandler.ts Added +9/-0 New TypeScript interface EventHandlerModule defining the contract for event handlers with events[] array and callback() function
src/index.ts Modified +40/-25 Refactored main entry point to use recursive collectHandlerFiles() function that discovers handlers in nested directories and registers them using the new defineEventHandler pattern
src/events/cleanup/branchCleanup.ts Added +23/-0 Moved from src/events/pull_request.closed/branchCleanup.ts and refactored to use defineEventHandler() with explicit events: ["pull_request.closed"] declaration
src/events/commands/addLinter.ts Added +129/-0 Moved from src/events/issue_comment.created/addLinter.ts and refactored to use defineEventHandler() with explicit events: ["issue_comment.created"] declaration
src/events/commands/ping.ts Added +45/-0 Moved from src/events/issue_comment.created/ping.ts and refactored to use defineEventHandler() with explicit events: ["issue_comment.created"] declaration
src/events/labeling/label-issue.ts Added +25/-0 Moved from src/events/issues.opened/auto-label.ts and refactored to use defineEventHandler() with explicit events: ["issues.opened"] declaration
src/events/labeling/label-pr.ts Added +52/-0 Moved from src/events/pull_request.opened/auto-label.ts and refactored to use defineEventHandler() with explicit events: ["pull_request.opened"] declaration
src/events/linting/checklint.ts Modified +37/-28 Moved from src/events/pull_request.opened/conventional-commits.ts and refactored to use defineEventHandler() with explicit events: ["workflow_run.completed"] declaration; updated log prefixes from [lint-bot] to [LINTER]
src/events/standards/conventional-commits.ts Added +59/-0 Moved from src/events/pull_request.opened/conventional-commits.ts and refactored to use defineEventHandler() with explicit events: ["pull_request.opened"] declaration
src/events/pull_request.closed/branchCleanup.ts Deleted +0/-20 Removed (moved to src/events/cleanup/branchCleanup.ts)
src/events/issue_comment.created/addLinter.ts Deleted +0/-125 Removed (moved to src/events/commands/addLinter.ts)
src/events/issue_comment.created/ping.ts Deleted +0/-42 Removed (moved to src/events/commands/ping.ts)
src/events/issues.opened/auto-label.ts Deleted +0/-22 Removed (moved to src/events/labeling/label-issue.ts)
src/events/pull_request.opened/auto-label.ts Deleted +0/-46 Removed (moved to src/events/labeling/label-pr.ts)
src/events/pull_request.opened/conventional-commits.ts Deleted +0/-56 Removed (moved to src/events/standards/conventional-commits.ts)

Total Changes: 17 files changed, +528 additions, -364 deletions

🗺️ Walkthrough:

graph TD
A["Event Emitted GitHub Webhook"] -->|"Probot receives"| B["index.ts Main Entry Point"]
B -->|"Recursively scans"| C["collectHandlerFiles Nested Directories"]
C -->|"Discovers handlers in"| D1["cleanup/"]
C -->|"Discovers handlers in"| D2["commands/"]
C -->|"Discovers handlers in"| D3["labeling/"]
C -->|"Discovers handlers in"| D4["standards/"]
C -->|"Discovers handlers in"| D5["linting/"]
D1 -->|"defineEventHandler"| E["EventHandlerModule events: string[] callback: function"]
D2 -->|"defineEventHandler"| E
D3 -->|"defineEventHandler"| E
D4 -->|"defineEventHandler"| E
D5 -->|"defineEventHandler"| E
E -->|"Registers with"| F["app.on Event Listener"]
F -->|"Triggers on match"| G["Handler Callback Executes Logic"]
G -->|"Returns result"| H["GitHub API Response"]
I["defineEventHandler Type-safe wrapper"] -.->|"Provides typing"| E
J["EventHandlerModule Interface"] -.->|"Defines contract"| E
Loading

🎯 Key Changes:

  • New Type System: Introduced EventHandlerModule interface and defineEventHandler() utility function that enable TypeScript to infer proper event types for each handler, improving IDE autocomplete and type safety
  • Nested Directory Structure: Reorganized handlers from flat event-type directories (issue_comment.created/, pull_request.opened/, etc.) into feature-based nested directories (cleanup/, commands/, labeling/, standards/, linting/), making the codebase more intuitive and scalable
  • Recursive Handler Discovery: Replaced the flat directory scanning logic with a recursive collectHandlerFiles() function that traverses all subdirectories, enabling unlimited nesting depth and better code organization
  • Explicit Event Declaration: Each handler now explicitly declares which events it handles via the events array, making event-to-handler relationships explicit and easier to audit
  • Improved Logging: Updated log messages to use consistent prefixes ([SUCCESS], [WARN]) and more descriptive output showing relative paths and event names
  • Editor Configuration: Added .zed/settings.json for Zed editor support with TypeScript/JavaScript LSP configuration for better development experience

📊 Impact Assessment:

  • Security: ✅ No negative impact. The refactoring maintains the same security model. Event handlers still validate permissions and access levels (e.g., addLinter.ts checks admin/maintain permissions). The explicit event declaration actually improves security by making handler responsibilities clearer.
  • Performance: ✅ Neutral to slight improvement. Recursive directory scanning at startup has minimal overhead compared to flat scanning. The handler registration logic is more efficient with early validation of handler structure. No runtime performance impact on event handling itself.
  • Maintainability: ✅ Significant improvement. The nested, feature-based structure is much more maintainable:
  • Related handlers are grouped together (e.g., all labeling logic in labeling/)
  • New handlers can be added to appropriate feature directories without modifying the discovery mechanism
  • The explicit events array makes handler responsibilities immediately clear
  • Type-safe defineEventHandler() prevents accidental misconfiguration
  • Easier to understand the codebase at a glance
  • Testing: ⚠️ Requires attention. The refactoring changes how handlers are discovered and registered:
  • Tests need to verify that handlers in nested directories are properly discovered
  • Tests should validate that the defineEventHandler() wrapper correctly preserves handler behavior
  • Integration tests should confirm that all event-to-handler mappings work correctly
  • Unit tests for individual handlers remain largely unchanged, but may need path updates
  • The recursive collectHandlerFiles() function should have dedicated tests to ensure it handles edge cases (empty directories, mixed file types, etc.)
⚙️ Settings

Severity Threshold: Medium — Balanced feedback — medium and high severity issues only.Change in Settings
Custom Rules: Define your own review rules — Set Custom Rules
PR Summary: Configure PR summary — Change in Settings

📖 User Guide
  • Once repos are connected, PR analysis is automatically enabled. You can disable analysis for this repo from beetleai.dev/analysis
  • Comment @beetle on any PR to start analysis manually
  • Comment @beetle stop to stop any ongoing analysis

Follow us: Beetle · X · LinkedIn

Comment on lines +19 to +20
} catch (err: any) {
if (err.status !== 422 && err.status !== 404) throw err;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The error handler silently swallows errors without logging, making it impossible to debug branch deletion failures. Additionally, using err: any bypasses TypeScript type safety. If the error object doesn't have a status property, the code could fail unexpectedly.

Confidence: 4/5

Suggested Fix
Suggested change
} catch (err: any) {
if (err.status !== 422 && err.status !== 404) throw err;
} catch (err: any) {
if (err.status === 422 || err.status === 404) {
// Branch already deleted or doesn't exist - this is acceptable
return;
}
console.error(`Failed to delete branch ${branchName}:`, err);
throw err;
}

Add logging to capture unexpected errors and make the status code check more explicit. This helps with debugging while still allowing expected errors (422, 404) to be handled gracefully.

Prompt for AI

Copy this prompt to your AI IDE to fix this issue locally:

In src/events/cleanup/branchCleanup.ts around line 19-20, the error handler silently swallows errors without logging, making debugging difficult. Additionally, the `err: any` type bypasses TypeScript safety. Add logging for unexpected errors and improve the error status check to be more explicit. Make sure to log the branch name and error details when deletion fails unexpectedly.

📍 This suggestion applies to lines 19-20

Comment on lines +76 to +79
const lintWorkflowContent = readFileSync(
join(__dirname, "../../templates/linter.yml"),
"utf-8",
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The readFileSync call is not wrapped in error handling. If the template file doesn't exist or is inaccessible, the entire handler will crash without notifying the user. This is a critical failure point that should be handled gracefully.

Confidence: 5/5

Suggested Fix
Suggested change
const lintWorkflowContent = readFileSync(
join(__dirname, "../../templates/linter.yml"),
"utf-8",
);
let lintWorkflowContent: string;
try {
lintWorkflowContent = readFileSync(
join(__dirname, "../../templates/linter.yml"),
"utf-8",
);
} catch (err) {
await context.octokit.rest.issues.createComment(
context.issue({
body: "❌ Failed to read lint workflow template. Please contact the repository administrator.",
}),
);
throw err;
}

Wrap the file read in a try-catch block to handle missing or inaccessible template files. Notify the user of the failure before throwing the error.

Prompt for AI

Copy this prompt to your AI IDE to fix this issue locally:

In src/events/commands/addLinter.ts around line 76-79, the readFileSync call is not wrapped in error handling. If the template file doesn't exist, the handler will crash silently. Add a try-catch block around the file read operation, and notify the user with a comment if the template file cannot be read.

📍 This suggestion applies to lines 76-79

Comment on lines +83 to +95
const { data: mainRef } = await context.octokit.rest.git.getRef({
owner,
repo,
ref: "heads/main",
});
const mainSha = mainRef.object.sha;

await context.octokit.rest.git.createRef({
owner,
repo,
ref: `refs/heads/${branchName}`,
sha: mainSha,
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The getRef and createRef API calls are not wrapped in error handling. If the main branch doesn't exist or the branch creation fails (e.g., branch already exists), the handler will crash without user notification. Additionally, if createRef fails, the file creation and PR creation will still attempt to execute against a non-existent branch.

Confidence: 5/5

Suggested Fix
Suggested change
const { data: mainRef } = await context.octokit.rest.git.getRef({
owner,
repo,
ref: "heads/main",
});
const mainSha = mainRef.object.sha;
await context.octokit.rest.git.createRef({
owner,
repo,
ref: `refs/heads/${branchName}`,
sha: mainSha,
});
let mainSha: string;
try {
const { data: mainRef } = await context.octokit.rest.git.getRef({
owner,
repo,
ref: "heads/main",
});
mainSha = mainRef.object.sha;
} catch (err) {
await context.octokit.rest.issues.createComment(
context.issue({
body: "❌ Failed to find the main branch. Does it exist?",
}),
);
throw err;
}
try {
await context.octokit.rest.git.createRef({
owner,
repo,
ref: `refs/heads/${branchName}`,
sha: mainSha,
});
} catch (err) {
await context.octokit.rest.issues.createComment(
context.issue({
body: "❌ Failed to create feature branch. Please try again.",
}),
);
throw err;
}

Wrap both API calls in try-catch blocks to handle failures gracefully and notify the user of what went wrong.

Prompt for AI

Copy this prompt to your AI IDE to fix this issue locally:

In src/events/commands/addLinter.ts around lines 83-95, the getRef and createRef API calls lack error handling. If the main branch doesn't exist or branch creation fails, the handler crashes without user feedback. Add separate try-catch blocks for both operations and notify the user of failures before throwing errors.

📍 This suggestion applies to lines 83-95

Comment on lines +97 to +104
await context.octokit.rest.repos.createOrUpdateFileContents({
owner,
repo,
path: workflowPath,
message: "ci: add lint workflow",
content: encodedContent,
branch: branchName,
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The createOrUpdateFileContents API call is not wrapped in error handling. If this operation fails (e.g., due to permission issues or API rate limiting), the branch will be left orphaned in the repository with no user notification. This creates resource leaks and confusion.

Confidence: 5/5

Suggested Fix
Suggested change
await context.octokit.rest.repos.createOrUpdateFileContents({
owner,
repo,
path: workflowPath,
message: "ci: add lint workflow",
content: encodedContent,
branch: branchName,
});
try {
await context.octokit.rest.repos.createOrUpdateFileContents({
owner,
repo,
path: workflowPath,
message: "ci: add lint workflow",
content: encodedContent,
branch: branchName,
});
} catch (err) {
// Clean up the orphaned branch
try {
await context.octokit.rest.git.deleteRef({
owner,
repo,
ref: `heads/${branchName}`,
});
} catch (cleanupErr) {
// Log cleanup failure but continue
console.error(`Failed to clean up branch ${branchName}:`, cleanupErr);
}
await context.octokit.rest.issues.createComment(
context.issue({
body: "❌ Failed to create workflow file. Please try again.",
}),
);
throw err;
}

Wrap the file creation in a try-catch block. If it fails, attempt to clean up the orphaned branch before notifying the user.

Prompt for AI

Copy this prompt to your AI IDE to fix this issue locally:

In src/events/commands/addLinter.ts around lines 97-104, the createOrUpdateFileContents call lacks error handling. If this fails, the branch is left orphaned. Add a try-catch block that attempts to clean up the branch if file creation fails, and notify the user of the failure.

📍 This suggestion applies to lines 97-104

Comment on lines +106 to +118
const { data: pr } = await context.octokit.rest.pulls.create({
owner,
repo,
title: "ci: add lint workflow",
head: branchName,
base: "main",
body: [
"This PR adds a GitHub Actions lint workflow to the repository.",
"",
"It was automatically generated by **devhub-bot** in response to the `!addlinter` command.",
"",
].join("\n"),
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The pulls.create API call is not wrapped in error handling. If PR creation fails, the user won't be notified, and they'll be left wondering if the operation succeeded. The branch and file will exist but no PR will be created.

Confidence: 5/5

Suggested Fix
Suggested change
const { data: pr } = await context.octokit.rest.pulls.create({
owner,
repo,
title: "ci: add lint workflow",
head: branchName,
base: "main",
body: [
"This PR adds a GitHub Actions lint workflow to the repository.",
"",
"It was automatically generated by **devhub-bot** in response to the `!addlinter` command.",
"",
].join("\n"),
});
let pr;
try {
const response = await context.octokit.rest.pulls.create({
owner,
repo,
title: "ci: add lint workflow",
head: branchName,
base: "main",
body: [
"This PR adds a GitHub Actions lint workflow to the repository.",
"",
"It was automatically generated by **devhub-bot** in response to the `!addlinter` command.",
"",
].join("\n"),
});
pr = response.data;
} catch (err) {
await context.octokit.rest.issues.createComment(
context.issue({
body: "❌ Failed to create pull request. The branch and workflow file were created, but the PR could not be opened. Please create the PR manually.",
}),
);
throw err;
}

Wrap the PR creation in a try-catch block to handle failures and notify the user appropriately.

Prompt for AI

Copy this prompt to your AI IDE to fix this issue locally:

In src/events/commands/addLinter.ts around lines 106-118, the pulls.create call lacks error handling. If PR creation fails, the user receives no feedback. Add a try-catch block to handle failures and notify the user that the branch and file were created but the PR could not be opened.

📍 This suggestion applies to lines 106-118

Comment on lines +38 to +43
await context.octokit.rest.issues.createComment({
owner,
repo,
issue_number: context.payload.issue.number,
body: reply,
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The createComment API call is not wrapped in error handling. If this operation fails (due to permission issues, rate limiting, or network errors), the handler will crash without notifying the user or logging the error. This leaves the user without feedback about whether their command succeeded.

Confidence: 5/5

Suggested Fix
Suggested change
await context.octokit.rest.issues.createComment({
owner,
repo,
issue_number: context.payload.issue.number,
body: reply,
});
try {
await context.octokit.rest.issues.createComment({
owner,
repo,
issue_number: context.payload.issue.number,
body: reply,
});
} catch (err) {
console.error(`Failed to post ping response: ${err}`);
throw err;
}

Wrap the API call in a try-catch block to handle failures gracefully and log the error for debugging purposes.

Prompt for AI

Copy this prompt to your AI IDE to fix this issue locally:

In src/events/commands/ping.ts around lines 38-43, the createComment API call lacks error handling. If the comment posting fails, the user receives no feedback. Add a try-catch block to handle failures and log the error for debugging.

📍 This suggestion applies to lines 38-43

@devhub-bot

devhub-bot Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Note

Linting checks passed successfully 🎉

All formatting and code quality checks are clean.

You're good to merge 🚀

Comment on lines +21 to +23
await context.octokit.rest.issues.addLabels(
context.issue({ labels: labelsToApply.map((l) => l.name) }),
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The addLabels API call is not wrapped in error handling. If this operation fails (due to permission issues, rate limiting, or network errors), the handler will crash without notifying the user or logging the error.

Confidence: 5/5

Suggested Fix
Suggested change
await context.octokit.rest.issues.addLabels(
context.issue({ labels: labelsToApply.map((l) => l.name) }),
);
try {
await context.octokit.rest.issues.addLabels(
context.issue({ labels: labelsToApply.map((l) => l.name) }),
);
} catch (err) {
console.error(`Failed to add labels to issue: ${err}`);
throw err;
}

Wrap the API call in a try-catch block to handle failures gracefully and log the error for debugging purposes.

Prompt for AI

Copy this prompt to your AI IDE to fix this issue locally:

In src/events/labeling/label-issue.ts around lines 21-23, the addLabels API call lacks error handling. If the operation fails, the handler crashes without logging. Add a try-catch block to handle failures and log the error for debugging.

📍 This suggestion applies to lines 21-23

Comment on lines +17 to +19
for (const label of labelsToApply) {
await ensureLabelExists(context, label);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The ensureLabelExists function is called in a loop without error handling. If label creation fails for any reason, the handler will crash and subsequent labels won't be processed. This could leave the issue in an inconsistent state with only some labels applied.

Confidence: 4/5

Suggested Fix
Suggested change
for (const label of labelsToApply) {
await ensureLabelExists(context, label);
}
for (const label of labelsToApply) {
try {
await ensureLabelExists(context, label);
} catch (err) {
console.error(`Failed to ensure label exists: ${label}`, err);
throw err;
}

Wrap the ensureLabelExists call in a try-catch block to handle failures gracefully and log which label failed to be created.

Prompt for AI

Copy this prompt to your AI IDE to fix this issue locally:

In src/events/labeling/label-issue.ts around lines 17-19, the ensureLabelExists call in the loop lacks error handling. If label creation fails, the handler crashes and subsequent labels won't be processed. Add a try-catch block to handle failures and log which label failed.

📍 This suggestion applies to lines 17-19

Comment on lines +12 to +15
const commits = await context.octokit.paginate(
context.octokit.rest.pulls.listCommits,
{ owner, repo, pull_number, per_page: 100 },
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The paginate API call is not wrapped in error handling. If this operation fails (due to permission issues, rate limiting, or network errors), the handler will crash without notifying the user or logging the error.

Confidence: 5/5

Suggested Fix
Suggested change
const commits = await context.octokit.paginate(
context.octokit.rest.pulls.listCommits,
{ owner, repo, pull_number, per_page: 100 },
);
let commits;
try {
commits = await context.octokit.paginate(
context.octokit.rest.pulls.listCommits,
{ owner, repo, pull_number, per_page: 100 },
);
} catch (err) {
console.error(`Failed to fetch commits for PR #${pull_number}: ${err}`);
throw err;
}

Wrap the API call in a try-catch block to handle failures gracefully and log the error for debugging purposes.

Prompt for AI

Copy this prompt to your AI IDE to fix this issue locally:

In src/events/labeling/label-pr.ts around lines 12-15, the paginate API call lacks error handling. If fetching commits fails, the handler crashes without logging. Add a try-catch block to handle failures and log the error for debugging.

📍 This suggestion applies to lines 12-15

Comment on lines +44 to +46
for (const label of labelsToApply) {
await ensureLabelExists(context, label);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The ensureLabelExists function is called in a loop without error handling. If label creation fails for any reason, the handler will crash and subsequent labels won't be processed. This could leave the PR in an inconsistent state with only some labels applied.

Confidence: 5/5

Suggested Fix
Suggested change
for (const label of labelsToApply) {
await ensureLabelExists(context, label);
}
for (const label of labelsToApply) {
try {
await ensureLabelExists(context, label);
} catch (err) {
console.error(`Failed to ensure label exists: ${label.name}`, err);
throw err;
}

Wrap the ensureLabelExists call in a try-catch block to handle failures gracefully and log which label failed to be created.

Prompt for AI

Copy this prompt to your AI IDE to fix this issue locally:

In src/events/labeling/label-pr.ts around lines 44-46, the ensureLabelExists call in the loop lacks error handling. If label creation fails, the handler crashes and subsequent labels won't be processed. Add a try-catch block to handle failures and log which label failed.

📍 This suggestion applies to lines 44-46

Comment on lines +48 to +50
await context.octokit.rest.issues.addLabels(
context.issue({ labels: labelsToApply.map((l) => l.name) }),
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The addLabels API call is not wrapped in error handling. If this operation fails (due to permission issues, rate limiting, or network errors), the handler will crash without notifying the user or logging the error.

Confidence: 5/5

Suggested Fix
Suggested change
await context.octokit.rest.issues.addLabels(
context.issue({ labels: labelsToApply.map((l) => l.name) }),
);
try {
await context.octokit.rest.issues.addLabels(
context.issue({ labels: labelsToApply.map((l) => l.name) }),
);
} catch (err) {
console.error(`Failed to add labels to PR #${pull_number}: ${err}`);
throw err;
}

Wrap the API call in a try-catch block to handle failures gracefully and log the error for debugging purposes.

Prompt for AI

Copy this prompt to your AI IDE to fix this issue locally:

In src/events/labeling/label-pr.ts around lines 48-50, the addLabels API call lacks error handling. If the operation fails, the handler crashes without logging. Add a try-catch block to handle failures and log the error for debugging.

📍 This suggestion applies to lines 48-50

Comment on lines +46 to +51
await context.octokit.rest.issues.createComment({
owner,
repo,
issue_number: pullNumber,
body,
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The createComment API call is not wrapped in error handling. If this operation fails (due to permission issues, rate limiting, or network errors), the handler will crash without logging the error or notifying the user. This leaves the PR without feedback about the lint workflow result.

Confidence: 5/5

Suggested Fix
Suggested change
await context.octokit.rest.issues.createComment({
owner,
repo,
issue_number: pullNumber,
body,
});
try {
await context.octokit.rest.issues.createComment({
owner,
repo,
issue_number: pullNumber,
body,
});
} catch (err) {
context.log.error(`[LINTER] Failed to post lint workflow comment: ${String(err)}`);
throw err;
}

Wrap the API call in a try-catch block to handle failures gracefully and log the error for debugging purposes.

Prompt for AI

Copy this prompt to your AI IDE to fix this issue locally:

In src/events/linting/checklint.ts around lines 46-51, the createComment API call lacks error handling. If the operation fails, the handler crashes without logging. Add a try-catch block to handle failures and log the error for debugging.

📍 This suggestion applies to lines 46-51

Comment on lines +19 to +22
const commits = await context.octokit.paginate(
context.octokit.rest.pulls.listCommits,
{ owner, repo, pull_number, per_page: 100 },
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The paginate API call is not wrapped in error handling. If this operation fails (due to permission issues, rate limiting, or network errors), the handler will crash without logging the error or notifying the user.

Confidence: 5/5

Suggested Fix
Suggested change
const commits = await context.octokit.paginate(
context.octokit.rest.pulls.listCommits,
{ owner, repo, pull_number, per_page: 100 },
);
let commits;
try {
commits = await context.octokit.paginate(
context.octokit.rest.pulls.listCommits,
{ owner, repo, pull_number, per_page: 100 },
);
} catch (err) {
console.error(`Failed to fetch commits for PR #${pull_number}: ${err}`);
throw err;
}

Wrap the API call in a try-catch block to handle failures gracefully and log the error for debugging purposes.

Prompt for AI

Copy this prompt to your AI IDE to fix this issue locally:

In src/events/standards/conventional-commits.ts around lines 19-22, the paginate API call lacks error handling. If fetching commits fails, the handler crashes without logging. Add a try-catch block to handle failures and log the error for debugging.

📍 This suggestion applies to lines 19-22

"",
].join("\n");

await context.octokit.rest.issues.createComment(context.issue({ body }));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The createComment API call is not wrapped in error handling. If this operation fails (due to permission issues, rate limiting, or network errors), the handler will crash without logging the error or notifying the user of the validation results.

Confidence: 5/5

Suggested Fix
Suggested change
await context.octokit.rest.issues.createComment(context.issue({ body }));
try {
await context.octokit.rest.issues.createComment(context.issue({ body }));
} catch (err) {
console.error(`Failed to post conventional commits validation comment: ${err}`);
throw err;
}

Wrap the API call in a try-catch block to handle failures gracefully and log the error for debugging purposes.

Prompt for AI

Copy this prompt to your AI IDE to fix this issue locally:

In src/events/standards/conventional-commits.ts around line 57, the createComment API call lacks error handling. If the operation fails, the handler crashes without logging. Add a try-catch block to handle failures and log the error for debugging.

@beetle-ai

beetle-ai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Summary by Beetle

This PR refactors the event handler naming convention across the codebase by renaming the defineEventHandler function to defineEvent. This is a straightforward API naming improvement that makes the function name more concise and consistent with common naming patterns in similar frameworks. The change is applied uniformly across all event handler modules in the application.

📁 File Changes Summary (Consolidated across all commits):

File Status Changes Description
src/events/cleanup/branchCleanup.ts
src/events/commands/addLinter.ts
src/events/commands/ping.ts
src/events/labeling/label-issue.ts
src/events/labeling/label-pr.ts
src/events/linting/checklint.ts
src/events/standards/conventional-commits.ts
Modified +14/-14 Updated all event handler modules to use the new defineEvent function name instead of defineEventHandler. Each file's import statement and function call were updated consistently.
src/lib/eventHandler.ts Modified +1/-1 Renamed the exported function from defineEventHandler to defineEvent in the core event handler library.

Total Changes: 8 files changed, +15 additions, -15 deletions

🎯 Key Changes:

  • Function Rename: defineEventHandlerdefineEvent across the entire codebase
  • Scope: Applied to 7 event handler modules covering multiple event types:
  • Cleanup events (branch cleanup)
  • Command events (ping, addLinter)
  • Labeling events (issue and PR labeling)
  • Linting events (workflow run checks)
  • Standards events (conventional commits)
  • Consistency: All import statements and function calls updated uniformly
  • No Logic Changes: This is purely a naming refactor with zero functional impact

📊 Impact Assessment:

  • Security: ✅ No security implications. This is a pure naming change with no behavioral modifications.
  • Performance: ✅ No performance impact. The function logic remains identical; only the name has changed.
  • Maintainability: ✅ Positive Impact. The shorter name defineEvent is more concise and easier to type. It aligns better with common naming conventions in similar frameworks (e.g., Vue's defineComponent, Nuxt's defineEventHandler context). The change improves code readability and reduces verbosity.
  • Testing: ✅ No testing implications. Since this is a pure rename with no logic changes, existing tests should continue to pass without modification. However, any tests that reference the old function name by string would need updating.
⚙️ Settings

Severity Threshold: Medium — Balanced feedback — medium and high severity issues only.Change in Settings
Custom Rules: Define your own review rules — Set Custom Rules
PR Summary: Configure PR summary — Change in Settings

📖 User Guide
  • Once repos are connected, PR analysis is automatically enabled. You can disable analysis for this repo from beetleai.dev/analysis
  • Comment @beetle on any PR to start analysis manually
  • Comment @beetle stop to stop any ongoing analysis

Follow us: Beetle · X · LinkedIn

@beetle-ai

beetle-ai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

✅ You're good to merge this PR! No issues found. Great job!

Settings
⚙️ Settings

Severity Threshold: Medium — Balanced feedback — medium and high severity issues only.Change in Settings
Custom Rules: Define your own review rules — Set Custom Rules
PR Summary: Configure PR summary — Change in Settings

📖 User Guide
  • Once repos are connected, PR analysis is automatically enabled. You can disable analysis for this repo from beetleai.dev/analysis
  • Comment @beetle on any PR to start analysis manually
  • Comment @beetle stop to stop any ongoing analysis

@devhub-bot

devhub-bot Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Note

Linting checks passed successfully 🎉

All formatting and code quality checks are clean.

You're good to merge 🚀

@calebephrem
calebephrem merged commit b9135e3 into open-devhub:main Aug 6, 2026
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactor code restructure

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant