Skip to content

feat: reopen PR + notify contributor on request decision - #74

Merged
ripgrim merged 3 commits into
mainfrom
reopen-on-request-approval
Jul 7, 2026
Merged

feat: reopen PR + notify contributor on request decision#74
ripgrim merged 3 commits into
mainfrom
reopen-on-request-approval

Conversation

@ripgrim

@ripgrim ripgrim commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

What

When Tripwire auto-closes a PR (or issue) and the contributor appeals via Request a review, an approving maintainer now:

  1. Reopens the exact PR/issue that was appealed for.
  2. Notifies the contributor of the outcome — on both approve and deny — via a GitHub comment (the only channel that reaches an external contributor), alongside the existing in-app request_decided event.

Previously decide() only mutated the blacklist/whitelist and told the contributor nothing.

How

  • Link the request to the closed content (so approval reopens the right PR, not a guess): the block comment's appeal link now carries &ref=<n>&ct=<pull_request|issue>; the request form captures it; submit stores it on contributor_requests (githubRef + contentType). Backward compatible — legacy links without a ref just skip auto-reopen.
  • packages/github: new reopenPullRequest / reopenIssue helpers.
  • packages/core/pr-comment: buildAppealUrl ref params + renderDecisionComment (bot-branded, respects prefs; handles the reopen-failed edge, e.g. deleted head branch).
  • decide(): best-effort reopen + notify runs outside the DB transaction with errors isolated — a GitHub hiccup never fails the committed decision. Logs github_pr_reopened / github_issue_reopened on reopen.

Covers both PRs and issues.

Testing

  • Unit: 5 new pr-comment tests (appeal-link ref, renderDecisionComment approve/deny/reopen-failed/bot-name). Full suite green (core, web 110, research 37, tools 4).
  • Live E2E: drove the real renderBlockedCommentclosePullRequest → real requests.decide tRPC procedure against g-r-i-m/playground. Verified approve → PR reopened + approval comment + blacklist lifted + events logged; deny → PR stayed closed + denial comment. All seeded state cleaned up.

Migration

Adds two nullable columns to contributor_requests (github_ref, content_type). Applied via pnpm db:push.

Summary by CodeRabbit

  • New Features

    • Added support for unblock requests on pull requests and issues, including reference-aware appeal links.
    • Approval and denial decisions can now post clearer comments, with automatic reopen attempts for approved unblock requests.
  • Bug Fixes

    • Blocked PR and issue comments now link to the correct referenced item.
    • If an automatic reopen fails, the request still completes and the comment explains the outcome.

When Tripwire auto-closes a PR/issue, the appeal link now carries the
content ref (&ref=&ct=). On an unblock request decision, decide() reopens
the exact PR/issue on approval and posts a GitHub comment notifying the
contributor of the outcome (approve and deny), alongside the existing
in-app request_decided event.

- schema: contributor_requests gains githubRef + contentType
- pr-comment: buildAppealUrl carries ref; renderDecisionComment for notices
- github: reopenPullRequest / reopenIssue helpers
- decide: best-effort reopen+notify outside the txn, errors isolated
@vercel

vercel Bot commented Jul 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
tripwire Canceled Canceled Jul 7, 2026 10:43pm

Request Review

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

React Doctor found no new issues. 🎉

Reviewed by React Doctor for commit 0b03e97.

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@ripgrim, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 34 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: df905fb0-7e38-4e3f-937a-493d5b8139af

📥 Commits

Reviewing files that changed from the base of the PR and between 8c64233 and 0b03e97.

📒 Files selected for processing (3)
  • .github/workflows/react-doctor.yml
  • apps/web/src/integrations/trpc/routers/requests.ts
  • apps/web/src/routes/request.$owner.$repo.tsx
📝 Walkthrough

Walkthrough

This PR adds support for reopening previously closed GitHub pull requests or issues when an "unblock" contributor request is approved. It introduces new database columns (githubRef, contentType) on contributorRequests, new GitHub API helpers (reopenPullRequest, reopenIssue), extended comment-rendering functions (buildAppealUrl, renderDecisionComment) with corresponding tests, TRPC router changes to persist appeal metadata and trigger a best-effort GitHub notification/reopen after a decision, and frontend route changes to carry ref/contentType query parameters through the submission flow. A standalone diagnostic E2E test file was also added.

Changes

Cohort: Unblock appeal reopen feature

  • DB schema: new AppealContentType type; githubRef and contentType columns added to contributorRequests
  • GitHub API: new reopenPullRequest and reopenIssue helper functions
  • Core comment rendering: buildAppealUrl and RenderCommentInput extended with ref/contentType/contentNumber; new renderDecisionComment function and RenderDecisionInput type; new re-exports in package index; filter-pipeline threads contentNumber into blocked comments
  • TRPC requests router: submit input extended with ref/contentType; decide mutation fetches repo/org and performs post-decision GitHub notification/reopen
  • Frontend route: query params ref/ct parsed and forwarded in submit payload

Sequence Diagram(s)

Included within the hidden review stack artifact.

Compact metadata

  • Related issues: None found
  • Related PRs: None found
  • Suggested labels: enhancement, needs-review
  • Suggested reviewers: (none specified)

Poem
A rabbit hops through closed PR gates,
With reopen keys it navigates,
Comments now speak of appeals anew,
Ref and type carried clean and true,
Hop, commit, reopen — celebrate!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main change: reopening appealed content and notifying contributors on request decisions, though it mentions PRs more than issues.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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.

React Doctor query-destructure-result: read only { data } from the
whoami/vouch useQuery calls instead of holding the whole result.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 3

🧹 Nitpick comments (1)
apps/web/src/_hookdiag.e2e.test.ts (1)

1-1: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

File naming doesn't follow kebab-case convention.

_hookdiag.e2e.test.ts uses a leading underscore and lacks a dash between words. As per coding guidelines, "Files: kebab-case (rule-card-grid.tsx)". Rename to something like hook-diag.e2e.test.ts.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/_hookdiag.e2e.test.ts` at line 1, Rename the test file to follow
the project’s kebab-case file naming convention; the current
`_hookdiag.e2e.test.ts` name uses a leading underscore and missing word
separators. Update the filename to a kebab-case variant such as the one used by
the hook diagnostics e2e test, and make sure any references to the file name in
the test setup or imports are updated accordingly.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/web/src/_hookdiag.e2e.test.ts`:
- Around line 3-15: The hook config test currently only logs results, so it can
never fail and provides no regression coverage. Update the
`_hookdiag.e2e.test.ts` test body to include real assertions on the `fetch`
responses and parsed app data (using the existing `createAppJwt`, `fetch`, and
`test.runIf` flow), or move this diagnostic logic out of the test suite into a
non-test script if it is meant only for manual debugging.

In `@apps/web/src/integrations/trpc/routers/requests.ts`:
- Around line 361-389: The reopen audit event in notifyDecisionOnGithub is only
emitted after addComment succeeds, so a failed comment can drop the
github_pr_reopened/github_issue_reopened log even when the reopen itself worked.
Move the logEvent call to run immediately after the successful reopen path,
before the best-effort GitHub comment send, and keep addComment separate so
comment failures do not block the audit trail.

In `@packages/db/src/schema/requests.ts`:
- Around line 38-41: The schema in requests.ts adds githubRef and contentType,
but there is no corresponding tracked Drizzle migration. Add a new migration
that updates the underlying requests table to include github_ref and
content_type, and make sure the migration is recorded in the same migration flow
used for other schema changes so the DB matches the requests schema definition.

---

Nitpick comments:
In `@apps/web/src/_hookdiag.e2e.test.ts`:
- Line 1: Rename the test file to follow the project’s kebab-case file naming
convention; the current `_hookdiag.e2e.test.ts` name uses a leading underscore
and missing word separators. Update the filename to a kebab-case variant such as
the one used by the hook diagnostics e2e test, and make sure any references to
the file name in the test setup or imports are updated accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 302c1464-7e54-4084-aa45-0e9e013cefd2

📥 Commits

Reviewing files that changed from the base of the PR and between c4f0a4d and 8c64233.

📒 Files selected for processing (9)
  • apps/web/src/_hookdiag.e2e.test.ts
  • apps/web/src/integrations/trpc/routers/requests.ts
  • apps/web/src/routes/request.$owner.$repo.tsx
  • packages/core/src/filter-pipeline.ts
  • packages/core/src/index.ts
  • packages/core/src/pr-comment.test.ts
  • packages/core/src/pr-comment.ts
  • packages/db/src/schema/requests.ts
  • packages/github/src/app.ts

Comment thread apps/web/src/_hookdiag.e2e.test.ts Outdated
Comment thread apps/web/src/integrations/trpc/routers/requests.ts Outdated
Comment thread packages/db/src/schema/requests.ts
- remove apps/web/src/_hookdiag.e2e.test.ts (throwaway diagnostic that hit
  live GitHub with hardcoded IDs; swept in by git add -A, not real coverage)
- notifyDecisionOnGithub: emit the github_pr_reopened/github_issue_reopened
  audit event immediately after a successful reopen, before the best-effort
  comment, so a comment failure can't drop the audit trail
- react-doctor.yml: fetch-depth: 0 so it diffs against the merge base and
  only reports issues this PR introduces
@ripgrim
ripgrim merged commit 3ddc257 into main Jul 7, 2026
9 of 11 checks passed
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.

1 participant