Skip to content

feat: implement issue #1440 — auto-rebase: extend auto_rebase_health.sh with fleet BEHIND/DIRTY observability (AC7) - #1444

Merged
don-petry merged 3 commits into
mainfrom
dev-lead/issue-1440-20260803-0112
Aug 3, 2026
Merged

don-petry merged 3 commits into
mainfrom
dev-lead/issue-1440-20260803-0112

Conversation

@don-petry

@don-petry don-petry commented Aug 3, 2026 •

Copy link
Copy Markdown
Collaborator

User description

Closes #1440

Implemented by dev-lead agent. Please review.


CodeAnt-AI Description

Add BEHIND and DIRTY pull request visibility to auto-rebase health reports

What Changed

  • Reports now show counts of open, non-draft, non-Dependabot pull requests that are BEHIND or DIRTY.
  • The report uses one pull request snapshot for both merge-state counts and the existing fan-out estimate.
  • Missing or empty pull request data now produces zero merge-state counts without failing the report.
  • Added coverage for eligible pull requests, draft and Dependabot exclusions, empty input, and report output.

Impact

✅ Clearer auto-rebase fleet status
✅ Faster identification of stale branches and merge conflicts
✅ Reports remain available when pull request data is unavailable

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

…sh with fleet BEHIND/DIRTY observability (AC7)
@don-petry
don-petry requested a review from a team as a code owner August 3, 2026 01:16
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@codeant-ai

codeant-ai Bot commented Aug 3, 2026 •

Copy link
Copy Markdown

🤖 CodeAnt AI — Review Status

Status Commit Started (UTC) Finished (UTC)
✅ Reviewed your PR 65529d0 Aug 03, 2026 · 01:16 01:18

@coderabbitai

coderabbitai Bot commented Aug 3, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

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

Next review available in: 29 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ca1ca647-a470-4964-946e-a0701d8fe1e0

📥 Commits

Reviewing files that changed from the base of the PR and between dc56e76 and c0bbb99.

📒 Files selected for processing (2)
  • scripts/auto_rebase_health.sh
  • tests/auto_rebase_health.bats

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.

@codeant-ai codeant-ai Bot added the size:L This PR changes 100-499 lines, ignoring generated files label Aug 3, 2026
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add BEHIND/DIRTY PR snapshot to auto-rebase health report

✨ Enhancement 🧪 Tests 🕐 20-40 Minutes

Grey Divider

AI Description

• Add AC7 observability: count open non-draft, non-Dependabot PRs in BEHIND vs DIRTY states.
• Pull a single open-PR snapshot and reuse it for both fan-out multiplier and merge-state metrics.
• Extend Bats coverage for merge-state summarization and report rendering defaults.
Diagram

graph TD
  A["GitHub Actions run"] --> B["auto_rebase_health.sh (main)"]
  B --> C["gh api: issue comments"] --> F["pure summarizers (jq)"]
  B --> D["gh api: workflow runs"] --> F
  B --> E["gh pr list: open PR snapshot"] --> F
  F --> G["render_report (Markdown)"] --> H["stdout + GITHUB_STEP_SUMMARY"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Persist per-run merge-state metrics (artifact or time series)
  • ➕ Makes trends measurable over time, not just a point-in-time snapshot
  • ➕ Allows correlating auto-rebase changes to merge-state improvements across days/weeks
  • ➖ More moving parts (storage, retention, aggregation)
  • ➖ Requires additional workflow steps and likely a separate reporting job
2. Fleet-wide (cross-repo) PR snapshot with elevated credentials
  • ➕ Matches the stated “fleet” goal more literally by aggregating across repos
  • ➖ Requires a cross-repo PAT and broader permissions
  • ➖ Higher blast radius and more complex failure/permission modes
3. Inline `gh pr list --jq` counting instead of passing full JSON
  • ➕ Avoids carrying the full PR JSON into render_report
  • ➕ Slightly simpler data plumbing
  • ➖ Less testable/pure (logic moves back into main)
  • ➖ Harder to reuse the same snapshot for multiple metrics

Recommendation: The current approach (single PR snapshot + pure jq summarizer + explicit report section) is the best fit for AC7: minimal permissions, low runtime cost, and good testability. If the team needs to prove improvement over time rather than per-run snapshots, add persisted per-run metrics as a follow-up.

Files changed (2) +116 / -8

Enhancement (1) +56 / -8
auto_rebase_health.shAdd mergeStateStatus BEHIND/DIRTY snapshot and report section +56/-8

Add mergeStateStatus BEHIND/DIRTY snapshot and report section

• Introduces summarize_merge_states() to count BEHIND vs DIRTY among open non-draft, non-Dependabot PRs. main() now fetches a single open-PR snapshot (author/isDraft/mergeStateStatus) and reuses it for both the behind-PR fan-out multiplier and the new AC7 observability section in render_report().

scripts/auto_rebase_health.sh

Tests (1) +60 / -0
auto_rebase_health.batsAdd unit tests for merge-state summarization and report rendering +60/-0

Add unit tests for merge-state summarization and report rendering

• Adds fixture PR JSON covering BEHIND/DIRTY/CLEAN plus draft and Dependabot exclusions. Introduces tests validating summarize_merge_states() counting/filtering behavior and verifies render_report() surfaces the new section and defaults counts to zero when PR JSON is absent.

tests/auto_rebase_health.bats

@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 fleet merge-state observability (AC7) to track the number of open, non-draft, and non-Dependabot pull requests that are either BEHIND or DIRTY. It updates the health report script to fetch and summarize these states using jq, and adds corresponding unit tests. The review feedback suggests improving the robustness of the jq filter by using optional chaining to safely handle null or missing author objects, using here-strings instead of printf pipes, and adding test coverage for these null/missing author edge cases.

Comment thread scripts/auto_rebase_health.sh Outdated
Comment thread tests/auto_rebase_health.bats
@don-petry
don-petry enabled auto-merge (squash) August 3, 2026 01:20
@don-petry
don-petry disabled auto-merge August 3, 2026 01:21
@qodo-code-review

qodo-code-review Bot commented Aug 3, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 50 rules

Grey Divider


Remediation recommended

1. PR snapshot capped at 200 ✓ Resolved 🐞 Bug ≡ Correctness
Description
main() fetches open PRs with gh pr list ... --limit 200, but the new AC7 section reports
BEHIND/DIRTY counts as a snapshot of the current open-PR queue. If the repo has >200 open PRs (or
the first 200 are draft/bot-heavy), the reported BEHIND/DIRTY counts will undercount and can
misrepresent the true backlog.
Code

scripts/auto_rebase_health.sh[R243-246]

+  prs_json="$(gh pr list --repo "$WORKFLOW_REPO" --state open --limit 200 \
+    --json author,isDraft,mergeStateStatus 2>/dev/null || echo '[]')"
+  [ -n "$prs_json" ] || prs_json='[]'
+
Relevance

●●● Strong

Team previously accepted fixes to avoid silent truncation/paginate listings for accurate metrics
(PRs #196, #1062).

PR-#196
PR-#1062

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The PR list used for BEHIND/DIRTY is explicitly limited to 200 items, but the report text positions
the numbers as a snapshot of the open-PR queue; therefore the metric is incomplete when open PRs
exceed the cap. The same script paginates other list-style data sources (comments/runs), reinforcing
that these reports intend completeness.

scripts/auto_rebase_health.sh[239-245]
scripts/auto_rebase_health.sh[156-158]
scripts/auto_rebase_health.sh[186-191]
scripts/auto_rebase_health.sh[223-237]
PR-#196

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The AC7 BEHIND/DIRTY metrics (and behind-PR multiplier) are computed from a PR list capped at 200 items, but the report describes it as a snapshot of the open PR queue. This can produce misleading undercounts.

### Issue Context
The PR list is fetched once in `main()` and then passed into `render_report()` for `summarize_merge_states()`.

### Fix Focus Areas
- scripts/auto_rebase_health.sh[239-246]
- scripts/auto_rebase_health.sh[156-158]
- scripts/auto_rebase_health.sh[186-191]

### Suggested fix
Implement one (or both) of:
1) Increase the cap substantially and make it configurable (e.g., `PR_LIST_LIMIT=${PR_LIST_LIMIT:-1000}`) and use `--limit "$PR_LIST_LIMIT"`.
2) Detect potential truncation (e.g., `len == PR_LIST_LIMIT`) and render a warning/note in the report (or label the counts as partial) so the metric can’t be mistaken for complete coverage.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

Comment thread scripts/auto_rebase_health.sh Outdated
donpetry-bot
donpetry-bot previously approved these changes Aug 3, 2026

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

Automated review — APPROVED ✓

Risk: MEDIUM
Reviewed commit: 65529d06dbdde0a5fd50e7938397ba0c4d583cf2
Review mode: triage-approved (single reviewer)

Summary

Confirms the triage assessment: this PR extends scripts/auto_rebase_health.sh with an AC7 fleet merge-state section (counts of open non-draft, non-Dependabot PRs that are BEHIND vs DIRTY), refactors main() to pull one open-PR snapshot shared by the existing behind-PR multiplier and the new metric, and adds 6 bats tests covering eligible PRs, draft/Dependabot exclusion, empty input, and report rendering. All new summarize/render logic is pure (no network), matching the file's established layout. No auth, secrets, workflow, or dependency changes.

Linked issue analysis

Closes #1440 (AC7 of #1416). The issue asks to surface per-run BEHIND/DIRTY counts over open non-draft, non-Dependabot PRs — repo-scoped is explicitly acceptable if fleet-wide needs a cross-repo PAT — with bats coverage per the existing pattern. The implementation does exactly this: repo-scoped snapshot with the PAT limitation documented in both the header comment and the rendered report, plus tests following tests/auto_rebase_health.bats conventions. Substantively addressed.

Findings

No blocking findings. Three open bot threads were evaluated on merit:

  1. Qodo — PR snapshot capped at 200 (correctness): valid observation, but the --limit 200 cap is pre-existing behavior (the behind-PR multiplier used the same cap before this PR); the change only consolidates the fetch. Non-blocking; a configurable limit or truncation note is a reasonable follow-up.
  2. Gemini (high) — jq null-safety on .author.login: not an actual bug. jq field access on null returns null, so .author.login // "" is safe for null/missing authors; the suggested .author?.login is a stylistic hardening only. The bats suite and CI pass as written.
  3. Gemini (low) — add null-author test: nice-to-have, non-blocking.

Secret scan: run_secret_scanning MCP tool not available in this session; gitleaks CI check passed. No secrets, credentials, or security-sensitive patterns in the diff.

CI status

All substantive checks green: shellcheck, ShellCheck, bats, unit-tests, Lint, actionlint, CodeQL (actions + python), Secret scan (gitleaks), SonarCloud Quality Gate, agent-shield, caller-stub-freeze, template-drift, holdout-guard, and all validate-* checks SUCCESS. Remaining PENDING/QUEUED/CANCELLED entries are the PR-review orchestration workflows themselves (pr-auto-review, dev-lead dispatch/ci-relay, review/review, Dismiss) and superseded runs — not code-quality gates.


Reviewed automatically by the PR-review agent (single-reviewer mode: fable 5). Reply if you need a human review.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Aug 3, 2026
@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — fix-reviews (applied)

Changes committed and pushed.

@don-petry
don-petry enabled auto-merge (squash) August 3, 2026 01:24
@don-petry
don-petry disabled auto-merge August 3, 2026 01:25

@don-petry don-petry left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Review — PR #1444 (#1440 auto-rebase fleet BEHIND/DIRTY observability)

Verified by running, not reading: 21/21 pass in tests/auto_rebase_health.bats, including the two that cover this story directly:

ok 20 render_report: surfaces BEHIND/DIRTY merge-state observability section
ok 21 render_report: absent PR JSON renders merge-state counts as zero

Zero failing checks. The graceful-degradation case (absent PR JSON → zeros rather than an error) is the right instinct for a report that must never break the workflow it rides on.

Endorsing Qodo's finding — verified independently

qodo-code-review flags that main() fetches with --limit 200 and the new merge-state counts would silently undercount above that. I checked the source rather than taking it on trust, and it holds (scripts/auto_rebase_health.sh:243):

prs_json="$(gh pr list --repo "$WORKFLOW_REPO" --state open --limit 200 \

What makes this more than a nitpick is that the same file already guards against exactly this, eleven lines earlier (:232):

#    not silently truncated at 100 runs (GitHub still caps created>= at 1,000).

So the run-fetch path is truncation-aware and the PR-fetch path is not — an internal inconsistency in one script, not a missing external convention. It also cuts against the repo's own posture that a bounded scan must log what it dropped rather than let a cap read as full coverage.

Ask: either raise/paginate the PR fetch, or detect hitting the cap and emit a ::warning:: plus a visible note in the rendered report ("counts based on the first 200 open PRs"). Either satisfies the principle; the warning is cheaper and matches the neighbouring comment's intent.

This is currently the only unresolved thread, so it is what stands between this PR and merge.


Worth noting for the record: qodo-code-review[bot] is now in TRUSTED_BOTS (added as the #1425 interim mitigation), so dev-lead can act on this thread directly. Before that change this exact situation — a correct third-party finding on a blocking thread — was unclearable by any automation and had to be relayed by hand. The mitigation is doing its job.

@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — review-changes (applied)

Changes committed and pushed.

@don-petry
don-petry enabled auto-merge (squash) August 3, 2026 01:30
@don-petry
don-petry disabled auto-merge August 3, 2026 01:31
@sonarqubecloud

sonarqubecloud Bot commented Aug 3, 2026

Copy link
Copy Markdown

@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — waiting on PR blockers (intent: review-changes)

PR: #1444
No changes were committed, but the PR still has blocking checks or reviews (failing or cancelled checks, or changes-requested reviews). The retry cron will re-attempt automatically. Next attempt after: 2026-08-03T02:02:11Z

@don-petry

Copy link
Copy Markdown
Collaborator Author

Note

@don-petry I reviewed this PR and no code changes were needed, but it still has blocking checks or reviews (failing or cancelled checks, or changes-requested reviews), so I cannot mark it done yet. I'll re-check automatically.
Next attempt after: 2026-08-03T02:02:11Z

@don-petry
don-petry enabled auto-merge (squash) August 3, 2026 01:32

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

Automated review — APPROVED ✓

Risk: MEDIUM
Reviewed commit: c0bbb99936a41a28a67e6f38dfba2fad45acff9e
Review mode: triage-approved (single reviewer)

Summary

Adds BEHIND/DIRTY merge-state observability (AC7, #1440) to the auto-rebase health report. A new pure summarize_merge_states function counts open non-draft, non-Dependabot PRs by mergeStateStatus; the open-PR snapshot is fetched once and reused for the existing fan-out multiplier; a configurable PR_LIST_LIMIT (default 1000) with a truncation warning replaces the old hard 200 cap. Comprehensive bats tests cover eligible counts, draft/Dependabot exclusion, null/missing authors, empty input, and report rendering with/without truncation.

Linked issue analysis

Issue #1440 asks to surface per-run BEHIND vs DIRTY counts of open non-draft, non-Dependabot PRs, repo-scoped being explicitly acceptable when fleet-wide would need cross-repo PAT scope, covered by bats tests in the existing pattern. The PR delivers exactly this: repo-scoped counts with the PAT limitation documented in the report itself, pure functions matching the script's existing layout, and bats coverage per the established pattern. Substantively addressed.

Findings

No blocking findings. Verified: jq filters handle null/absent author safely (tested); herestring jq input and printf %s argument rendering leave no injection path; the gh pr list call is read-only with existing token scope; error fallbacks (|| echo '[]' / 0) keep the report best-effort as before. Behavioral note: the fan-out multiplier's PR cap rises from 200 to 1000 via the shared snapshot — an improvement, documented in the header. Triage's low-risk assessment is confirmed; classified MEDIUM only because this is non-trivial logic in an Actions-executed script. Secret scan MCP tool unavailable in this run; gitleaks CI check is green and the diff adds no secret-like content. Prior review threads are all resolved and dev-lead fix commits addressed earlier bot/owner review comments.

CI status

All substantive checks green at c0bbb99: bats, unit-tests, shellcheck (both), Lint, CodeQL, Analyze (actions/python), actionlint, gitleaks, agent-shield, holdout-guard, SonarCloud quality gate passed, CodeRabbit success. Remaining CANCELLED entries are superseded review/dispatch orchestration runs (review/review, dev-lead dispatch/ci-relay, Dismiss), not code-quality gates.


Reviewed automatically by the PR-review agent (single-reviewer mode: fable 5). Reply if you need a human review.

@don-petry
don-petry merged commit 9f42ae8 into main Aug 3, 2026
41 of 46 checks passed
@don-petry
don-petry deleted the dev-lead/issue-1440-20260803-0112 branch August 3, 2026 01:33
@donpetry-bot

Copy link
Copy Markdown
Contributor

Advisory bots were rate-limited; auto-approval is withheld until they recover. pr-review-sweep will re-review this PR after 2026-08-03T02:34:13Z.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L This PR changes 100-499 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

auto-rebase: extend auto_rebase_health.sh with fleet BEHIND/DIRTY observability (AC7)

2 participants