Skip to content

feat(ci): add PR path-based label routing and priority recommendation - #573

Merged
Astro-Han merged 1 commit into
devfrom
slock/pr-routing-triage
May 12, 2026
Merged

feat(ci): add PR path-based label routing and priority recommendation#573
Astro-Han merged 1 commit into
devfrom
slock/pr-routing-triage

Conversation

@Astro-Han

@Astro-Han Astro-Han commented May 12, 2026

Copy link
Copy Markdown
Owner

Summary

Add two conservative PR triage automations:

  • path-based scope routing via GitHub's official actions/labeler
  • one-shot priority recommendation via actions/github-script, posting a review comment instead of auto-applying P* labels

This keeps maintainer control over P0/P1 while reducing manual relabel work for routine PRs.

Why

Issue #135 asks for a first-pass PR queue that is easier to scan without turning priority into an opaque bot decision. The safe v1 boundary is:

  • automatically apply scope labels from changed paths
  • recommend P3 only for obvious low-risk PRs like docs, workflows, tests, and e2e-only changes
  • recommend P2 for app/desktop user-path changes and other non-low-risk paths
  • never auto-apply a priority label, and never auto-suggest P1/P0

I also aligned the path routing with the existing repo label taxonomy instead of inventing new labels. Concretely:

  • .github/workflows/** -> ci
  • packages/desktop-electron/** -> platform
  • packages/app/** -> app
  • packages/app/src/components/**, packages/ui/**, **/*.tsx -> ui
  • packages/opencode/** -> harness
  • docs/**, **/*.md -> documentation

That preserves current label vocabulary while still matching the issue's routing intent.

Related Issue

Closes #135.

Human Review Status

Pending. A human should make the final merge decision after reviewing the final diff and verification evidence.

Review Focus

  • Whether the path-to-label mapping is the right conservative fit for the repo's existing labels.
  • Whether the priority helper stays within the intended v1 boundary: only P2/P3 recommendations, no auto-priority labels, no reviewer assignment.
  • Whether the one-shot marker behavior is correct for opened, synchronize, and reopened without creating repeat triage noise.

Risk Notes

  • No product code, UI, or release workflow behavior changed.
  • The new triage workflow runs on pull_request_target, but it checks out the PR base SHA only. It does not execute code from the PR head.
  • Priority is posted as a review comment with a marker instead of mutating P* labels. That keeps maintainer override simple and avoids accidental P1/P0 escalation.
  • actions/labeler is configured against current repo labels (platform, harness, documentation) rather than the issue's placeholder names (desktop, opencode, docs) because those placeholder labels do not exist in the repo today.

How To Verify

actionlint .github/workflows/labeler.yml .github/workflows/pr-priority-triage.yml
Result: pass

bun --cwd packages/opencode test test/github/pr-routing-triage.test.ts
Result: 7 pass

bun --cwd packages/opencode typecheck
Result: pass

git diff --check
Result: pass

Sanity checks encoded in the contract test:
- PR #568 changed app src paths -> suggested P2
- PR #569 changed only e2e test paths -> suggested P3
- PR #571 changed only workflow + test paths -> suggested P3

Screenshots or Recordings

Not needed. This is CI automation with no visible UI change.

Checklist

  • Human review status is stated above as pending, approved, or not required
  • I linked the related issue, or stated why there is no issue
  • This PR has type, primary area, and priority labels, or I requested maintainer labeling
  • I described the review focus and any meaningful risks
  • I listed the relevant verification steps and the key result for each
  • I did not introduce unrelated refactors, dependencies, generated files, or file changes beyond the stated scope
  • I manually checked visible UI or copy changes when needed, with screenshots or recordings
  • I considered macOS and Windows impact for platform, packaging, updater, signing, paths, shell, or permissions changes
  • I called out docs, release notes, dependencies, permissions, credentials, deletion behavior, generated content, or local file changes when relevant
  • I reviewed the final diff for unrelated changes and suspicious dependency changes
  • I am targeting dev, and my PR title and commit messages use Conventional Commits in English

Summary by CodeRabbit

  • Chores

    • Added automated pull-request labeling rules covering CI, platform, app, UI, harness, and documentation.
    • Added workflows to sync labels and to post automated prioritization recommendations for PRs.
    • Added a helper that classifies changed files to suggest review priority.
  • Tests

    • Added tests validating the label/triage workflows and the prioritization helper’s classifications and review content.

Review Change Stack

@Astro-Han Astro-Han added enhancement New feature or request ci Continuous integration / GitHub Actions P2 Medium priority labels May 12, 2026
@coderabbitai

coderabbitai Bot commented May 12, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 8a04c3bd-ea4a-4133-988b-d86c78091381

📥 Commits

Reviewing files that changed from the base of the PR and between 3146e16 and 13f95f1.

📒 Files selected for processing (5)
  • .github/labeler.yml
  • .github/scripts/pr-priority-triage.js
  • .github/workflows/labeler.yml
  • .github/workflows/pr-priority-triage.yml
  • packages/opencode/test/github/pr-routing-triage.test.ts
✅ Files skipped from review due to trivial changes (2)
  • .github/workflows/labeler.yml
  • .github/labeler.yml
🚧 Files skipped from review as they are similar to previous changes (3)
  • .github/workflows/pr-priority-triage.yml
  • packages/opencode/test/github/pr-routing-triage.test.ts
  • .github/scripts/pr-priority-triage.js

📝 Walkthrough

Walkthrough

Adds path-based labeler rules, a priority-classifier helper script, two GitHub Actions workflows (labeler + triage), and tests that validate workflow metadata and triage outputs.

Changes

Automated PR Routing and Priority Triage

Layer / File(s) Summary
Label routing configuration and workflow
.github/labeler.yml, .github/workflows/labeler.yml
Adds glob->label mappings for ci, platform, app, ui, harness, and documentation, and a labeler workflow that syncs labels on pull_request_target events targeting dev.
Priority triage helper script
.github/scripts/pr-priority-triage.js
Exports TRIAGE_MARKER, classifyPriority(paths), and buildPriorityReview(paths); implements glob-to-regex matching, path normalization, and conservative P2/P3 classification with a marked markdown review body.
Priority triage workflow orchestration
.github/workflows/pr-priority-triage.yml
Workflow triggers on pull_request_target for dev, enforces per-PR concurrency, checks out base SHA, imports the helper via actions/github-script, lists PR files/reviews, skips if prior triage exists, and posts a one-shot COMMENT review with the computed priority.
Workflow contracts and triage logic tests
packages/opencode/test/github/pr-routing-triage.test.ts
Bun tests assert labeler routing keys/globs, workflow event filters/permissions/concurrency/pinned actions, and helper outputs (P3 for doc/workflow/test-only; P2 for user-path and mixed non-low-risk changes) and verify review body contains TRIAGE_MARKER and reservation guidance.

Sequence Diagram

sequenceDiagram
  participant PR as Pull Request
  participant Labeler as labeler workflow
  participant LabelerAction as actions/labeler
  participant Triage as pr-priority-triage workflow
  participant Script as pr-priority-triage.js
  participant GitHub as GitHub API

  PR->>Labeler: pull_request_target (opened/synchronized/reopened)
  Labeler->>LabelerAction: run globs to compute labels
  LabelerAction->>GitHub: set labels (ci/platform/app/ui/harness/documentation)
  
  PR->>Triage: pull_request_target (opened/synchronized/reopened)
  Triage->>Script: list PR files and existing reviews
  Script->>Script: classifyPriority(changed_paths)
  Script->>GitHub: detect existing TRIAGE_MARKER comment
  Script->>Script: buildPriorityReview(paths)
  Script->>GitHub: post COMMENT review with priority verdict
  Triage->>GitHub: log posted priority
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

github_actions

Poem

🐰 I hopped into the CI glade at dawn,

With globs and markers, labels neatly drawn,
A tiny script in fur—P2 or P3—
It nudges reviewers gently, merrily.
🎩✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding path-based label routing and priority recommendation as CI automation.
Description check ✅ Passed The description comprehensively follows the template with all major sections: Summary, Why, Related Issue, Human Review Status, Review Focus, Risk Notes, How To Verify, Screenshots/Recordings, and a complete Checklist.
Linked Issues check ✅ Passed The PR fully addresses #135's objectives: automatically applies scope labels via actions/labeler, recommends P3 for low-risk changes (docs, workflows, tests), recommends P2 for app/desktop/other non-low-risk paths, never auto-applies P1/P0, and keeps routing explainable with review comments.
Out of Scope Changes check ✅ Passed All changes are directly scoped to PR routing/triage automation: labeler configuration, triage script, two workflow files, and contract tests. No unrelated refactors, dependencies, or product code changes are present.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch slock/pr-routing-triage

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.

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Opus second-pass review — PR #573

Pass, no blockers.

Strengths

  • Security pattern correct: pull_request_target + actions/checkout with ref: github.event.pull_request.base.sha ensures the workflow never runs PR-from-fork head code while still having access to the repo token. This is the recommended pattern for triage workflows.
  • persist-credentials: false is fine here because both labeler and the github-script step use the API directly, not git push — no auth wiring needed.
  • Concurrency group pr-priority-triage-${pr.number} with cancel-in-progress: true correctly handles rapid pushes, and the TRIAGE_MARKER dedup ensures duplicate comments cannot happen even with race-cancel.
  • All third-party actions pinned to commit SHA (actions/checkout@de0fac2e..., actions/github-script@f28e40c7..., actions/labeler@8558fd74...), no @v6 floating tags.
  • Custom glob-to-regex in pr-priority-triage.js correctly handles **/ prefix ((?:.*/)?) and bare ** (.*). Traced docs/**, **/*.md, and packages/app/src/** — all behave as expected.
  • Conservative v1 design: never auto-applies a P label, always comments a recommendation, P1/P0 reserved for maintainer. This is exactly the right trust model.
  • Deliberate deviation from issue body: GPT chose real platform/harness/documentation labels over the issue body's placeholder desktop/opencode/docs because those don't exist in the repo. Documented in PR body. This is correct judgment — the workflow would have succeeded silently but applied no labels otherwise.
  • sync-labels: true is safe in this setup because the labeler only manages the 6 path-based labels declared in labeler.yml; maintainer-added P labels and other labels (release-gate, windows, flaky-test, etc.) are untouched.
  • Sanity cases in the contract test against recent real PRs are convincing:
    • PR #568 (production packages/app/src/** change) → P2 ✓
    • PR #569 (pure e2e test) → P3 ✓
    • PR #571 (CI workflow only) → P3 ✓
  • 7 contract tests cover the classifier paths, marker dedup, and glob edge cases.

Nit (no action)

  • pull_request_target with synchronize re-runs on every push, but the marker dedup means subsequent pushes do NOT update the recommendation if the scope changes drastically (e.g., a PR that started doc-only and grew to product code). Acceptable for v1 — the comment is advisory and maintainers can manually relabel. If this becomes a pain point, a future iteration could compare current paths to the marker-encoded snapshot and re-post when scope drifts beyond a threshold.

  • Could add an explicit note in PR body that sync-labels: true is intentionally limited to path-based labels and won't touch P-level or other manual labels. Helps future maintainers who scan the workflow and worry about label collisions.

Verdict

CI workflow + path-based labeler + advisory comment surface. No product code, no release workflow change, no UI/UX. Conservative v1 design with sound security pattern and good test coverage. Ready for engineering final from @GPT-X.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces an automated PR priority triage system, including a labeler configuration and a script to classify PRs as P2 or P3 based on changed file paths. Feedback focused on optimizing the triage script by memoizing compiled regular expressions and truncating the list of file paths in the triage reason to avoid hitting GitHub comment size limits and reduce noise.

Comment thread .github/scripts/pr-priority-triage.js
Comment thread .github/scripts/pr-priority-triage.js

@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.

🧹 Nitpick comments (1)
.github/labeler.yml (1)

16-21: ⚡ Quick win

Consider narrowing the **/*.tsx glob to exclude test files.

The **/*.tsx pattern will match all TypeScript JSX files in the repository, including test files (e.g., packages/app/e2e/**/*.tsx, **/test/**/*.tsx). This may dilute the signal if the ui label is intended primarily for production UI component changes.

If test TSX files should not be labeled as ui, consider adding exclusion patterns or constraining the glob to production directories.

🎯 Example: Exclude test directories from ui label
 ui:
   - changed-files:
       - any-glob-to-any-file:
           - "packages/app/src/components/**"
           - "packages/ui/**"
-          - "**/*.tsx"
+          - "packages/app/src/**/*.tsx"
+          - "packages/desktop-electron/src/**/*.tsx"

Note: Verify whether story files, E2E specs, or other .tsx files in test directories should also receive the ui label before applying this change.

🤖 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 @.github/labeler.yml around lines 16 - 21, The ui label's broad "**/*.tsx"
glob will match test/spec files; update the ui -> changed-files ->
any-glob-to-any-file entry to exclude test paths by removing or constraining the
"**/*.tsx" pattern and instead either target production dirs (e.g., package src
and ui folders already listed) or add exclusion patterns such as excluding
"**/test/**", "**/e2e/**", and filename patterns like "**/*.spec.tsx" and
"**/*.test.tsx"; modify the pattern(s) around the existing ui and
any-glob-to-any-file entries so only intended production UI .tsx files trigger
the label.
🤖 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.

Nitpick comments:
In @.github/labeler.yml:
- Around line 16-21: The ui label's broad "**/*.tsx" glob will match test/spec
files; update the ui -> changed-files -> any-glob-to-any-file entry to exclude
test paths by removing or constraining the "**/*.tsx" pattern and instead either
target production dirs (e.g., package src and ui folders already listed) or add
exclusion patterns such as excluding "**/test/**", "**/e2e/**", and filename
patterns like "**/*.spec.tsx" and "**/*.test.tsx"; modify the pattern(s) around
the existing ui and any-glob-to-any-file entries so only intended production UI
.tsx files trigger the label.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 356ab09b-9a40-4b94-8ac4-fd640a1839cf

📥 Commits

Reviewing files that changed from the base of the PR and between 422b515 and 3146e16.

📒 Files selected for processing (5)
  • .github/labeler.yml
  • .github/scripts/pr-priority-triage.js
  • .github/workflows/labeler.yml
  • .github/workflows/pr-priority-triage.yml
  • packages/opencode/test/github/pr-routing-triage.test.ts

@Astro-Han
Astro-Han force-pushed the slock/pr-routing-triage branch from 3146e16 to 13f95f1 Compare May 12, 2026 06:46
@Astro-Han
Astro-Han merged commit 97c5f07 into dev May 12, 2026
22 checks passed
@Astro-Han
Astro-Han deleted the slock/pr-routing-triage branch May 12, 2026 08:43
This was referenced May 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci Continuous integration / GitHub Actions enhancement New feature or request P2 Medium priority

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Automate pull request routing and priority triage

1 participant