Skip to content

ci: add PR triage tier bot#285

Open
brandon-pereira wants to merge 3 commits into
mainfrom
ci/add-pr-tier-bot
Open

ci: add PR triage tier bot#285
brandon-pereira wants to merge 3 commits into
mainfrom
ci/add-pr-tier-bot

Conversation

@brandon-pereira

@brandon-pereira brandon-pereira commented Jul 13, 2026

Copy link
Copy Markdown
Member

Adds a PR Triage workflow that auto-classifies each PR into a risk tier (1–4), labels it, and posts an explanatory comment.

Opened as a draft to test the workflow behavior before enabling it broadly.

What it does

  • Runs on pull_request to main (opened / synchronize / reopened / ready_for_review); skips drafts for the classify step.
  • A gating test job runs the pure classification logic via node --test before anything is labeled.
  • classify job applies a review/tier-N label and posts a sticky comment explaining why.

Risk tiers

Every PR lands in exactly one tier. Classification is checked top-down: Tier 4 wins first, then Tier 1, then Tier 2, otherwise Tier 3. Line counts exclude test files and trivial files (docs, lock files, config).

Tier Meaning Trigger Review process
🟢 Tier 1 — Trivial Docs, images, lock files, or a dependency bump. No functional code. Bot author (e.g. dependabot), or every changed file is trivial (docs / images / lock / .changeset/ / repo config / smoke-tests/ / non-release workflows / .github/scripts/). Auto-merge once CI passes. No human review.
🔵 Tier 2 — Low Risk Small, isolated change within a single package. No core SDK changes. < 200 prod lines and single-package and no core package.json edit and (for agent branches) < 50 prod lines across ≤ 3 files. AI review + quick human skim (5–15 min).
🟡 Tier 3 — Standard New logic, modified functionality, or changes spanning multiple packages. The default when a PR is neither trivial nor small-and-isolated: ≥ 200 prod lines, cross-package, a core package.json edit, or an agent branch that exceeds the Tier 2 size limits. Full human review — logic, architecture, edge cases.
🔴 Tier 4 — Critical Can break customers or the release pipeline. Touches core SDK source (node-opentelemetry, browser, otel-web, session-recorder) or release.yaml, or a very large diff (> 1000 prod lines human / > 400 agent). Deep review from a domain expert; sync walkthrough may be required.

Agent-branch guardrail

Branches prefixed claude/, agent/, or ai/ have a tighter Tier 2 ceiling (< 50 lines, ≤ 3 files) and a lower Tier 4 escalation threshold (> 400 lines vs. > 1000 for humans), so machine-generated diffs always get at least one mandatory human review.

Repo-specific adaptation

This feature is mainly based off HyperDX OSS , however, classification is tuned to this monorepo's layout:

  • Tier 4 (critical): core SDK sources — node-opentelemetry, browser, otel-web, session-recorder — and release.yaml.
  • Tier 1 (trivial): repo config, smoke-tests/, and non-release workflows.
  • Cross-package changes and core package.json edits block Tier 2.

Overriding a classification

Remove the bot-applied review/tier-* label and apply a different one by hand. Manual overrides are detected (via the label event actor) and preserved on subsequent pushes — the bot won't re-classify a PR a human has re-tiered.

Notes

  • No secrets required (uses the built-in GITHUB_TOKEN).
  • Because this PR only adds the pull_request workflow, it may not run on this PR itself — it takes effect for PRs opened after merge to main. Use the workflow_dispatch trigger (with a pr_number) to test against an existing PR.
  • Classification logic is unit-tested (80 tests, all passing).

Adds a PR Triage workflow that classifies each PR into a risk tier (1-4)
based on files touched, diff size, and author/branch, then labels the PR
and posts an explanatory comment.

Tier classification is adapted to this monorepo's package layout: core SDK
packages (node-opentelemetry, browser, otel-web, session-recorder) and the
release workflow are critical (Tier 4); repo config, smoke-tests, and
non-release workflows are trivial (Tier 1).

Classification logic is pure and unit-tested (node --test) and runs as a
gating job before the classify step.
@changeset-bot

changeset-bot Bot commented Jul 13, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: f83f801

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@greptile-apps

greptile-apps Bot commented Jul 13, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds automated risk-tier classification for pull requests. The main changes are:

  • A workflow for testing and running PR triage.
  • Tier labels and sticky explanatory comments.
  • Classification rules for file paths, diff size, dependency bumps, and agent branches.
  • Manual override handling, bulk dispatch support, and failure reporting.
  • Unit tests for the classification logic.

Confidence Score: 5/5

This looks safe to merge.

  • No new blocking issue qualifies for this follow-up review.
  • Classification failures now propagate to the workflow result.
  • The module loading and tested classification paths are consistent with the workflow setup.

Important Files Changed

Filename Overview
.github/scripts/pr-triage.js Runs classification, preserves manual overrides, updates labels and comments, and reports API failures.
.github/scripts/pr-triage-classify.js Implements file signals, dependency-bump checks, tier selection, and comment generation.
.github/scripts/tests/pr-triage-classify.test.js Covers classification helpers, thresholds, dependency bumps, tier outcomes, and comment content.
.github/workflows/pr-triage.yml Defines the pull-request and manual triggers, test gate, permissions, concurrency groups, and classification job.

Reviews (3): Last reviewed commit: "ci: harden triage dep-bump detection and..." | Re-trigger Greptile

Comment thread .github/workflows/pr-triage.yml
Comment thread .github/scripts/pr-triage.js
Comment thread .github/workflows/pr-triage.yml Outdated
@brandon-pereira brandon-pereira marked this pull request as ready for review July 13, 2026 21:56
@brandon-pereira brandon-pereira changed the title ci: add PR triage tier bot [DO NOT MERGE] ci: add PR triage tier bot4 Jul 13, 2026
@github-actions github-actions Bot added the review/tier-1 Trivial — auto-merge candidate once CI passes label Jul 13, 2026
@github-actions

github-actions Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

🟢 Tier 1 — Trivial

Docs, images, lock files, or a low-risk dependency bump (patch-level, or a minor bump of a non-OpenTelemetry dependency). No functional code changes detected.

Why this tier:

  • All files are docs / images / lock files

Review process: Auto-merge once CI passes. No human review required.
SLA: Resolves automatically.

Stats
  • Production files changed: 0
  • Production lines changed: 0 (+ 815 in test files, excluded from tier calculation)
  • Branch: ci/add-pr-tier-bot
  • Author: brandon-pereira

To override this classification, remove the review/tier-1 label and apply a different review/tier-* label. Manual overrides are preserved on subsequent pushes.

- pr-triage.js: collect per-PR failures and throw after the loop so a
  gating workflow can detect incomplete triage (bulk mode still continues
  past individual failures)
- pr-triage.yml: use inputs.pr_number || 'bulk' as the concurrency group
  fallback instead of github.run_id, so concurrent bulk dispatches serialize
Comment on lines +20 to +21
group: ${{ github.workflow }}-${{ github.event.pull_request.number ||
inputs.pr_number || 'bulk' }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Per-PR Runs Bypass Bulk Lock

A bulk dispatch uses the PR Triage-bulk group, while a pull-request event or targeted dispatch for PR #42 uses PR Triage-42. These runs can overlap even though both update PR #42. If a push starts the per-PR run while a bulk run is processing that PR, the bulk run can write its earlier classification last, leaving the tier label and sticky comment stale. Bulk processing and per-PR processing need coordination at the PR level.

Context Used: AGENTS.md (source)

Fix in Claude Code Fix in Conductor Fix in Cursor Fix in Codex

@brandon-pereira brandon-pereira changed the title [DO NOT MERGE] ci: add PR triage tier bot4 ci: add PR triage tier bot4 Jul 13, 2026
@brandon-pereira brandon-pereira changed the title ci: add PR triage tier bot4 ci: add PR triage tier bot Jul 13, 2026
Comment on lines +74 to +80
1: {
emoji: '🟢',
headline: 'Tier 1 — Trivial',
detail: 'Docs, images, lock files, or a dependency bump. No functional code changes detected.',
process: 'Auto-merge once CI passes. No human review required.',
sla: 'Resolves automatically.',
},

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think we need to be a bit more cautious with dependency version bumps. The OpenTelemetry SDK, for example, could potentially introduce breaking changes. If possible, I'd suggest treating any OpenTelemetry SDK version bump (major or minor) as T2. For non-OpenTelemetry dependencies, only major version bumps should be treated as T2.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@wrn14897 updated

Address PR #285 review feedback:
- parseSemver now parses abbreviated ranges (^1, 1.x, bare major) and is
  anchored so non-semver targets (git URLs, npm: aliases) return null
- Dependency-bump detection scopes out package metadata keys (version, name,
  ...), accumulates all version pairs per name so a duplicate name across
  blocks can't mask a risky bump, and fails closed for unparseable
  @opentelemetry/* bumps
- Label writes are now add-then-remove with 404-tolerant removal so concurrent
  runs never leave a PR unlabeled or fail on an already-removed label
- Corrected the staleness-guard comment to reflect that it narrows, not closes,
  the bulk-vs-per-PR race

Adds 12 regression tests (112 total, all passing).
@brandon-pereira brandon-pereira requested a review from wrn14897 July 14, 2026 22:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review/tier-1 Trivial — auto-merge candidate once CI passes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants