Skip to content

Conversation

@youngchingjui
Copy link
Owner

@youngchingjui youngchingjui commented Dec 29, 2025

Summary

Implement webhook handling for PR labels to trigger the createDependentPR workflow when PRs are labeled with "I2PR: Update PR".

Features Implemented

🔗 Webhook Handler Foundation

  • New Handler: handlePullRequestLabelCreateDependentPR enqueues createDependentPR jobs
  • Enhanced Schema: Extended PullRequestPayloadSchema with label, number, and sender fields
  • Route Integration: Added PR labeled event routing in webhook endpoint

🎯 How It Works

  1. GitHub Event: PR gets labeled with "I2PR: Update PR"
  2. Webhook Processing: Validates payload and extracts job data
  3. Job Queuing: Enqueues createDependentPR job with:
    • repoFullName (e.g., "owner/repo")
    • pullNumber (PR number)
    • githubLogin (who applied the label)
    • githubInstallationId (for GitHub App auth)
  4. Worker Processing: (Next PR) Worker will create dependent branch/PR

🧪 Test Coverage

  • Handler validates required fields and environment
  • Handler enqueues jobs with correct payload structure
  • Webhook route correctly routes labeled events
  • Integration test covers full webhook → handler flow

Technical Details

New Files

lib/webhook/github/handlers/pullRequest/label.createDependentPR.handler.ts
__tests__/lib/webhook/handlers/pullRequest/label.createDependentPR.handler.test.ts  
__tests__/api/webhook/github.route.test.ts

Modified Files

app/api/webhook/github/route.ts - Added labeled event routing
lib/webhook/github/types.ts - Extended PullRequestPayloadSchema

Example Usage

When a PR is labeled "I2PR: Update PR", this triggers:

// Enqueues Redis job:
{
  name: "createDependentPR",
  data: {
    repoFullName: "owner/repo",
    pullNumber: 42,
    githubLogin: "developer", 
    githubInstallationId: "12345"
  }
}

Context & Sequence

This PR is part of breaking down the large PR #1413 into manageable pieces:

  1. PR Improve test infrastructure and Jest configuration #1437: Test infrastructure fixes
  2. PR Add container security enhancements to prevent command injection #1438: Container security enhancements
  3. This PR: Webhook handler foundation
  4. 🔄 Next: Worker infrastructure (Redis/Neo4j setup)
  5. 🔄 Final: CreateDependentPR core workflow

Testing

pnpm test __tests__/lib/webhook/handlers/pullRequest/
pnpm test __tests__/api/webhook/github.route.test.ts

Addresses the webhook handling requirements from Issue #1399.

🤖 Generated with Claude Code


Update: Adjust handler to no-op per review feedback

  • Addressed RLC-001 and RLC-002: The worker does not yet recognize a createDependentPR job name. To keep this PR scoped to webhook routing and avoid enqueueing unknown jobs, the handler now performs a no-op.
  • Changes:
    • handlePullRequestLabelCreateDependentPR no longer enqueues a job. It validates required fields, logs a clear message indicating the webhook was received, and returns a small { status: "noop", ... } result.
    • Updated unit tests to reflect the no-op behavior (removed Redis/job enqueue expectations; assert logging/return value instead).
  • Route tests remain the same (they mock the handler and only assert routing/invocation).

Rationale

  • This keeps the boundary clean and avoids enqueueing jobs that would fail in the worker until the job schema/handler support is added in a follow-up PR.

Verification

  • Jest tests for the updated handler and webhook route pass locally:
    • __tests__/lib/webhook/handlers/pullRequest/label.createDependentPR.handler.test.ts
    • __tests__/api/webhook/github.route.test.ts

Next steps

  • Follow-up PR to register the createDependentPR job type in the worker and wire up the actual enqueue logic.

Summary by CodeRabbit

  • New Features

    • Pull requests can now be automatically processed when labeled with "i2pr: update pr"
    • Enhanced webhook system to recognize and route pull request label events with proper signature verification
  • Tests

    • Added comprehensive unit tests for webhook routing and signature verification
    • Added tests for pull request label event handling, including validation of required payload fields

✏️ Tip: You can customize this high-level summary in your review settings.

## Features Added
- **PR Label Webhook Handler**: Triggers createDependentPR job when PR is labeled with "I2PR: Update PR"
- **Enhanced PullRequestPayloadSchema**: Added label, number, and sender fields to support label events
- **Webhook Route Integration**: Added routing logic to handle PR labeled events

## Technical Implementation
- Created `handlePullRequestLabelCreateDependentPR` handler to enqueue worker jobs
- Extended webhook payload validation to include required fields for the dependent PR workflow
- Added comprehensive tests covering both handler logic and route integration

## How It Works
1. GitHub sends webhook when PR gets labeled with "I2PR: Update PR"
2. Webhook validates payload and extracts: `repoFullName`, `pullNumber`, `githubLogin`, `githubInstallationId`
3. Handler enqueues `createDependentPR` job onto the workflow-jobs Redis queue
4. Worker (to be implemented in next PR) will process the job and create dependent branch/PR

## Test Coverage
- [x] Handler validates required fields and throws appropriate errors
- [x] Handler enqueues job with correct payload structure
- [x] Route integration correctly routes labeled events to handler
- [x] REDIS_URL environment validation

This provides the webhook foundation for the createDependentPR workflow feature requested in Issue #1399.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@cursor
Copy link

cursor bot commented Dec 29, 2025

You have run out of free Bugbot PR reviews for this billing cycle. This will reset on January 19.

To receive reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 29, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

This PR adds webhook event handling for GitHub pull requests labeled with "i2pr: update pr". It introduces a new handler function that validates the payload, logs receipt of the event, and returns metadata without further processing. Type definitions are extended to support optional fields (PR number, label name, sender).

Changes

Cohort / File(s) Summary
Test: Webhook Routing
__tests__/api/webhook/github.route.test.ts
Tests webhook route for two scenarios: issue labeled with "i2pr: resolve issue" (invokes handleIssueLabelAutoResolve) and PR labeled with "i2pr: update pr" (invokes handlePullRequestLabelCreateDependentPR). Validates signature verification and correct argument passing.
Test: PR Label Handler
__tests__/lib/webhook/handlers/pullRequest/label.createDependentPR.handler.test.ts
Tests handlePullRequestLabelCreateDependentPR handler for noop path (returns metadata and logs event) and error path (throws on missing required fields in payload).
Implementation: Handler
lib/webhook/github/handlers/pullRequest/label.createDependentPR.handler.ts
New async handler function that validates PR payload fields (owner, repo, number, login), constructs repoFullName, logs a no-op receipt message, and returns status with event metadata.
Implementation: Route
app/api/webhook/github/route.ts
Adds routing logic for pull_request labeled events; extracts label name, normalizes to lowercase, and invokes handlePullRequestLabelCreateDependentPR when label is "i2pr: update pr".
Type Definitions
lib/webhook/github/types.ts
Extends PullRequestPayloadSchema with optional fields: number (at top level and within pull_request object), label (with name string), and sender (with login string).

Possibly related PRs

  • PR #1241: Both touch webhook routing and pull-request handler integration, extending event dispatch capabilities.
  • PR #1252: Both modify GitHub webhook routing and pull_request payload handling with schema-based event dispatching.
  • PR #1244: Both update app/api/webhook/github/route.ts and PullRequest payload types, one adding labeled-PR routing while the other refactors signature verification.

Suggested labels

AI generated, dependent-pr

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/webhook-handler-pr-labels

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

…n- Remove job queue enqueue from handlePullRequestLabelCreateDependentPR\n- Validate payload and log receipt with context; return a small noop result\n- Update unit tests to assert noop behavior and remove Redis/job assertions\n\nThis scopes the PR to webhook routing only; worker job wiring will be added in a follow-up PR.
@vercel vercel bot temporarily deployed to Preview – issue-to-pr-realtime December 29, 2025 03:48 Inactive
@vercel vercel bot temporarily deployed to Preview – issue-to-pr-storybook December 29, 2025 03:48 Inactive
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
lib/webhook/github/handlers/pullRequest/label.createDependentPR.handler.ts (1)

17-17: Consider using nullish coalescing (??) for the pullNumber fallback.

The current code uses ||, which would skip payload.number if it were 0. While GitHub PR numbers are always positive integers (starting at 1), using ?? is more semantically correct and defensive:

-  const pullNumber = payload.number || payload.pull_request?.number
+  const pullNumber = payload.number ?? payload.pull_request?.number
🔎 Proposed change
-  const pullNumber = payload.number || payload.pull_request?.number
+  const pullNumber = payload.number ?? payload.pull_request?.number
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9205a4e and a424f95.

📒 Files selected for processing (5)
  • __tests__/api/webhook/github.route.test.ts
  • __tests__/lib/webhook/handlers/pullRequest/label.createDependentPR.handler.test.ts
  • app/api/webhook/github/route.ts
  • lib/webhook/github/handlers/pullRequest/label.createDependentPR.handler.ts
  • lib/webhook/github/types.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js,jsx,mts,mjs}

📄 CodeRabbit inference engine (.cursor/rules/code-structure.mdc)

Avoid barrel files: do not create files whose sole purpose is to re-export symbols from multiple modules; prefer importing from original module paths to maintain clear dependency graphs and better tree-shaking

Files:

  • __tests__/lib/webhook/handlers/pullRequest/label.createDependentPR.handler.test.ts
  • __tests__/api/webhook/github.route.test.ts
  • app/api/webhook/github/route.ts
  • lib/webhook/github/handlers/pullRequest/label.createDependentPR.handler.ts
  • lib/webhook/github/types.ts
🧠 Learnings (2)
📓 Common learnings
Learnt from: youngchingjui
Repo: youngchingjui/issue-to-pr PR: 1282
File: shared/src/ports/events/publisher.ts:16-19
Timestamp: 2025-09-22T09:24:26.840Z
Learning: youngchingjui prefers to manage PR scope tightly and defer technical debt improvements to future PRs rather than expanding the current PR's scope, even for related consistency issues.
📚 Learning: 2025-09-12T01:44:51.070Z
Learnt from: youngchingjui
Repo: youngchingjui/issue-to-pr PR: 1241
File: app/api/webhook/github/route.ts:85-90
Timestamp: 2025-09-12T01:44:51.070Z
Learning: In the webhook handlers at app/api/webhook/github/route.ts, runWithInstallationId is intentionally not awaited to allow fire-and-forget background processing of long-running workflows, avoiding webhook timeouts. The team plans to migrate these to proper queues/workers in a separate issue later.

Applied to files:

  • __tests__/lib/webhook/handlers/pullRequest/label.createDependentPR.handler.test.ts
  • __tests__/api/webhook/github.route.test.ts
  • app/api/webhook/github/route.ts
  • lib/webhook/github/handlers/pullRequest/label.createDependentPR.handler.ts
🧬 Code graph analysis (3)
__tests__/api/webhook/github.route.test.ts (3)
app/api/webhook/github/route.ts (1)
  • POST (61-361)
lib/webhook/github/handlers/issue/label.autoResolveIssue.handler.ts (1)
  • handleIssueLabelAutoResolve (11-47)
lib/webhook/github/handlers/pullRequest/label.createDependentPR.handler.ts (1)
  • handlePullRequestLabelCreateDependentPR (8-40)
app/api/webhook/github/route.ts (1)
lib/webhook/github/handlers/pullRequest/label.createDependentPR.handler.ts (1)
  • handlePullRequestLabelCreateDependentPR (8-40)
lib/webhook/github/handlers/pullRequest/label.createDependentPR.handler.ts (1)
lib/webhook/github/types.ts (1)
  • PullRequestPayload (51-51)
🔇 Additional comments (6)
app/api/webhook/github/route.ts (2)

14-14: LGTM! Import follows project conventions.

The import path uses the path alias and matches the existing handler import patterns.


171-189: LGTM! PR label routing logic is well-structured.

The implementation follows the existing pattern for issue label routing (lines 113-134), properly extracts the installationId (safe since installation is required by the schema), normalizes the label name to lowercase, and routes to the appropriate handler. Unhandled labels are correctly ignored.

__tests__/lib/webhook/handlers/pullRequest/label.createDependentPR.handler.test.ts (1)

1-56: LGTM! Comprehensive test coverage for the no-op handler.

The test suite properly covers:

  • The happy path: validates return shape and log message content
  • The error path: validates that missing required fields throw an error
  • Mock hygiene: uses mockRestore() to clean up the console spy
lib/webhook/github/types.ts (1)

37-38: LGTM! Type extensions properly support PR label events.

The added optional fields (number, label, pull_request.number, sender) align with the shape of GitHub's PR labeled webhook payloads and follow the same patterns used in IssuesPayloadSchema (lines 27, 30). Making these fields optional correctly accommodates different PR event types.

Also applies to: 42-42, 48-48

lib/webhook/github/handlers/pullRequest/label.createDependentPR.handler.ts (1)

8-40: LGTM! Handler correctly implements no-op validation boundary.

The implementation properly:

  • Validates all required fields with appropriate type checks
  • Provides descriptive error messages
  • Logs the receipt with full context (repo, PR number, user, installationId)
  • Returns structured metadata for future use

The no-op approach aligns with the PR objectives to defer job enqueueing until worker schema support is ready.

__tests__/api/webhook/github.route.test.ts (1)

19-21: LGTM! Route integration test properly validates the PR label webhook flow.

The test:

  • Properly mocks the handler (lines 19-21)
  • Creates a valid payload with all required fields including number, label, sender, and installation
  • Generates a correct HMAC signature for webhook verification
  • Verifies the handler is called exactly once with the expected arguments
  • Follows the same pattern as the existing issue label test (lines 46-81)

Also applies to: 83-119

@youngchingjui youngchingjui merged commit 7406054 into main Dec 29, 2025
4 checks passed
@youngchingjui youngchingjui deleted the feature/webhook-handler-pr-labels branch December 29, 2025 04:02
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