Repository navigation
feat: alert #frontend-releases when the sheriff run degrades - #14735
Conversation
The job exits non-zero when it cannot resolve the on-call sheriff, but a failing scheduled workflow only notifies whoever last pushed to main — in practice nobody. That is precisely how the placeholder Datadog config survived for weeks while every run warned and still reported success. Post the reason to #frontend-releases instead, where the rotation actually looks. The script surfaces why it degraded through a step output so the alert is actionable without opening the run, and the post is continue-on-error so Slack being unreachable never masks the underlying result.
📄 Knowledge reviewDosu skipped reviewing this PR because your organization has used its |
🎭 Playwright: ✅ 1790 passed, 0 failed · 1 flaky📊 Browser Reports
📦 Bundle: 8.26 MB gzip ⚪ 0 BDetailsSummary
Category Glance App Entry Points — 3.64 kB (baseline 3.64 kB) • ⚪ 0 BMain entry bundles and manifests Status: 1 unchanged Graph Workspace — 1.35 MB (baseline 1.35 MB) • ⚪ 0 BGraph editor runtime, canvas, workflow orchestration Status: 2 unchanged Views & Navigation — 114 kB (baseline 114 kB) • ⚪ 0 BTop-level views, pages, and routed surfaces Status: 17 unchanged Panels & Settings — 551 kB (baseline 551 kB) • ⚪ 0 BConfiguration panels, inspectors, and settings screens Status: 26 unchanged User & Accounts — 27 kB (baseline 27 kB) • ⚪ 0 BAuthentication, profile, and account management bundles Status: 10 unchanged Editors & Dialogs — 124 kB (baseline 124 kB) • ⚪ 0 BModals, dialogs, drawers, and in-app editors Status: 7 unchanged UI Components — 72.1 kB (baseline 72.1 kB) • ⚪ 0 BReusable component library chunks Status: 15 unchanged Data & Services — 3.48 MB (baseline 3.48 MB) • ⚪ 0 BStores, services, APIs, and repositories Status: 17 unchanged Utilities & Hooks — 387 kB (baseline 387 kB) • ⚪ 0 BHelpers, composables, and utility bundles Status: 36 unchanged Vendor & Third-Party — 15.7 MB (baseline 15.7 MB) • ⚪ 0 BExternal libraries and shared vendor chunks Status: 16 unchanged Other — 12.8 MB (baseline 12.8 MB) • ⚪ 0 BBundles that do not match a named category Status: 281 unchanged ⚡ Performance Report
Show regressions
All metrics
Historical variance (last 15 runs)
Trend (last 15 commits on main)
Raw data{
"timestamp": "2026-08-05T11:29:25.243Z",
"gitSha": "459ba1056a997af5dce78456d4c742f71a06bb34",
"branch": "fix/sheriff-slack-alert-20260804",
"measurements": [
{
"name": "canvas-idle",
"durationMs": 2070.177000000001,
"styleRecalcs": 7,
"styleRecalcDurationMs": 8.647000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 583.8480000000001,
"heapDeltaBytes": 5806096,
"heapUsedBytes": 71389140,
"domNodes": 14,
"jsHeapTotalBytes": 23330816,
"scriptDurationMs": 24.366000000000003,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-idle",
"durationMs": 2060.681000000045,
"styleRecalcs": 11,
"styleRecalcDurationMs": 9.806,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 489.98199999999997,
"heapDeltaBytes": 6020184,
"heapUsedBytes": 71597452,
"domNodes": 22,
"jsHeapTotalBytes": 23068672,
"scriptDurationMs": 16.224000000000004,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-mouse-sweep",
"durationMs": 2221.3199999999915,
"styleRecalcs": 80,
"styleRecalcDurationMs": 51.172,
"layouts": 12,
"layoutDurationMs": 4.95,
"taskDurationMs": 1196.959,
"heapDeltaBytes": -12727472,
"heapUsedBytes": 52939688,
"domNodes": -280,
"jsHeapTotalBytes": 23179264,
"scriptDurationMs": 146.21200000000002,
"eventListeners": -153,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1854.7199999999293,
"styleRecalcs": 76,
"styleRecalcDurationMs": 41.359,
"layouts": 12,
"layoutDurationMs": 3.965,
"taskDurationMs": 874.13,
"heapDeltaBytes": 617896,
"heapUsedBytes": 66174560,
"domNodes": 59,
"jsHeapTotalBytes": 24907776,
"scriptDurationMs": 116.82000000000001,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1726.364999999987,
"styleRecalcs": 31,
"styleRecalcDurationMs": 17.578,
"layouts": 6,
"layoutDurationMs": 0.619,
"taskDurationMs": 435.857,
"heapDeltaBytes": 8748344,
"heapUsedBytes": 74317176,
"domNodes": 76,
"jsHeapTotalBytes": 23330816,
"scriptDurationMs": 26.262999999999998,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1734.4650000000001,
"styleRecalcs": 32,
"styleRecalcDurationMs": 17.792999999999996,
"layouts": 6,
"layoutDurationMs": 0.6040000000000002,
"taskDurationMs": 401.64500000000004,
"heapDeltaBytes": 8548636,
"heapUsedBytes": 74004048,
"domNodes": 76,
"jsHeapTotalBytes": 23330816,
"scriptDurationMs": 22.074,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "dom-widget-clipping",
"durationMs": 615.0590000000307,
"styleRecalcs": 12,
"styleRecalcDurationMs": 8.388000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 398.7419999999999,
"heapDeltaBytes": -10534432,
"heapUsedBytes": 54950696,
"domNodes": 20,
"jsHeapTotalBytes": 23592960,
"scriptDurationMs": 58.79899999999999,
"eventListeners": 0,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "dom-widget-clipping",
"durationMs": 573.3629999999721,
"styleRecalcs": 11,
"styleRecalcDurationMs": 7.205000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 379.06600000000003,
"heapDeltaBytes": -11143552,
"heapUsedBytes": 54660388,
"domNodes": 18,
"jsHeapTotalBytes": 23855104,
"scriptDurationMs": 55.338,
"eventListeners": 0,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-idle",
"durationMs": 2040.6429999999887,
"styleRecalcs": 9,
"styleRecalcDurationMs": 7.9959999999999996,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 778.5680000000001,
"heapDeltaBytes": 7174920,
"heapUsedBytes": 66590748,
"domNodes": -281,
"jsHeapTotalBytes": 3514368,
"scriptDurationMs": 121.23699999999998,
"eventListeners": -149,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-idle",
"durationMs": 2038.4300000000621,
"styleRecalcs": 10,
"styleRecalcDurationMs": 8.701,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 723.1210000000001,
"heapDeltaBytes": 7291844,
"heapUsedBytes": 66599132,
"domNodes": -282,
"jsHeapTotalBytes": 3514368,
"scriptDurationMs": 104.30099999999999,
"eventListeners": -147,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-pan",
"durationMs": 2239.70300000002,
"styleRecalcs": 68,
"styleRecalcDurationMs": 15.665,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1374.695,
"heapDeltaBytes": -5744992,
"heapUsedBytes": 55012616,
"domNodes": -285,
"jsHeapTotalBytes": 3776512,
"scriptDurationMs": 444.624,
"eventListeners": -177,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-pan",
"durationMs": 2180.1699999999755,
"styleRecalcs": 69,
"styleRecalcDurationMs": 14.428000000000003,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1273.362,
"heapDeltaBytes": 4418456,
"heapUsedBytes": 65351124,
"domNodes": -283,
"jsHeapTotalBytes": 4493312,
"scriptDurationMs": 412.798,
"eventListeners": -149,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-zoom",
"durationMs": 3313.207000000034,
"styleRecalcs": 65,
"styleRecalcDurationMs": 17.087,
"layouts": 60,
"layoutDurationMs": 8.618,
"taskDurationMs": 1632.54,
"heapDeltaBytes": 1532112,
"heapUsedBytes": 64078272,
"domNodes": -288,
"jsHeapTotalBytes": 6922240,
"scriptDurationMs": 573.0959999999999,
"eventListeners": -153,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "large-graph-zoom",
"durationMs": 3232.1660000000065,
"styleRecalcs": 66,
"styleRecalcDurationMs": 17.218,
"layouts": 60,
"layoutDurationMs": 8.168999999999999,
"taskDurationMs": 1542.712,
"heapDeltaBytes": -843904,
"heapUsedBytes": 61208068,
"domNodes": -288,
"jsHeapTotalBytes": 6397952,
"scriptDurationMs": 533.9900000000001,
"eventListeners": -153,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "minimap-idle",
"durationMs": 2030.0240000000258,
"styleRecalcs": 7,
"styleRecalcDurationMs": 7.199000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 753.9970000000001,
"heapDeltaBytes": 6892232,
"heapUsedBytes": 68049404,
"domNodes": -283,
"jsHeapTotalBytes": 3252224,
"scriptDurationMs": 114.16900000000001,
"eventListeners": -149,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "minimap-idle",
"durationMs": 2029.6520000000555,
"styleRecalcs": 8,
"styleRecalcDurationMs": 8.039000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 765.461,
"heapDeltaBytes": 6982272,
"heapUsedBytes": 68165088,
"domNodes": -286,
"jsHeapTotalBytes": 3776512,
"scriptDurationMs": 118.41600000000001,
"eventListeners": -147,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 623.2610000000136,
"styleRecalcs": 47,
"styleRecalcDurationMs": 14.974000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 456.618,
"heapDeltaBytes": -10594552,
"heapUsedBytes": 55341968,
"domNodes": 20,
"jsHeapTotalBytes": 24641536,
"scriptDurationMs": 132.686,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 579.2729999999437,
"styleRecalcs": 48,
"styleRecalcDurationMs": 12.173,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 408.6360000000001,
"heapDeltaBytes": -10875020,
"heapUsedBytes": 54887172,
"domNodes": 22,
"jsHeapTotalBytes": 24641536,
"scriptDurationMs": 124.02400000000002,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-idle",
"durationMs": 2017.9769999999735,
"styleRecalcs": 10,
"styleRecalcDurationMs": 9.135999999999997,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 504.505,
"heapDeltaBytes": 5717260,
"heapUsedBytes": 71394436,
"domNodes": 20,
"jsHeapTotalBytes": 23855104,
"scriptDurationMs": 16.327,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-idle",
"durationMs": 1998.2400000000098,
"styleRecalcs": 8,
"styleRecalcDurationMs": 6.508999999999998,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 513.9039999999999,
"heapDeltaBytes": 5511928,
"heapUsedBytes": 71442704,
"domNodes": 16,
"jsHeapTotalBytes": 23592960,
"scriptDurationMs": 16.648999999999997,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1753.8089999999897,
"styleRecalcs": 79,
"styleRecalcDurationMs": 38.47,
"layouts": 16,
"layoutDurationMs": 4.630999999999999,
"taskDurationMs": 829.657,
"heapDeltaBytes": -19259208,
"heapUsedBytes": 46450596,
"domNodes": -282,
"jsHeapTotalBytes": 21737472,
"scriptDurationMs": 93.82300000000001,
"eventListeners": -153,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1688.1200000000263,
"styleRecalcs": 75,
"styleRecalcDurationMs": 34.758,
"layouts": 16,
"layoutDurationMs": 4.267,
"taskDurationMs": 765.261,
"heapDeltaBytes": -3543516,
"heapUsedBytes": 62174260,
"domNodes": 62,
"jsHeapTotalBytes": 24379392,
"scriptDurationMs": 88.863,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-transition-enter",
"durationMs": 1384.2150000000402,
"styleRecalcs": 18,
"styleRecalcDurationMs": 28.497,
"layouts": 14,
"layoutDurationMs": 11.136999999999997,
"taskDurationMs": 928.3459999999999,
"heapDeltaBytes": 4887088,
"heapUsedBytes": 96862012,
"domNodes": 13673,
"jsHeapTotalBytes": 15466496,
"scriptDurationMs": 34.582,
"eventListeners": 2375,
"totalBlockingTimeMs": 115,
"frameDurationMs": 16.666666666666696,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "viewport-pan-sweep",
"durationMs": 8872.242000000027,
"styleRecalcs": 249,
"styleRecalcDurationMs": 42.741,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 5256.614,
"heapDeltaBytes": 16266320,
"heapUsedBytes": 75918412,
"domNodes": -281,
"jsHeapTotalBytes": 12095488,
"scriptDurationMs": 1707.747,
"eventListeners": -163,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "viewport-pan-sweep",
"durationMs": 8300.100000000042,
"styleRecalcs": 250,
"styleRecalcDurationMs": 42.1,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 4513.258,
"heapDeltaBytes": 10434424,
"heapUsedBytes": 70613192,
"domNodes": -282,
"jsHeapTotalBytes": 6066176,
"scriptDurationMs": 1372.434,
"eventListeners": -133,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-idle",
"durationMs": 17709.161999999993,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 17683.706000000002,
"heapDeltaBytes": -29804352,
"heapUsedBytes": 184291980,
"domNodes": -8312,
"jsHeapTotalBytes": -3608576,
"scriptDurationMs": 573.459,
"eventListeners": -16387,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.776666666666763,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "vue-large-graph-idle",
"durationMs": 18134.26900000002,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 18073.129999999997,
"heapDeltaBytes": -36998988,
"heapUsedBytes": 176259212,
"domNodes": -8312,
"jsHeapTotalBytes": -14356480,
"scriptDurationMs": 576.533,
"eventListeners": -16387,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.780000000000047,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "vue-large-graph-pan",
"durationMs": 22358.757000000027,
"styleRecalcs": 164,
"styleRecalcDurationMs": 24.961000000000013,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 22314.426,
"heapDeltaBytes": -54623080,
"heapUsedBytes": 153971140,
"domNodes": -8312,
"jsHeapTotalBytes": -10948608,
"scriptDurationMs": 917.844,
"eventListeners": -16381,
"totalBlockingTimeMs": 615,
"frameDurationMs": 17.776666666666642,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "vue-large-graph-pan",
"durationMs": 22331.067000000075,
"styleRecalcs": 163,
"styleRecalcDurationMs": 22.84,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 22298.166999999998,
"heapDeltaBytes": -44335060,
"heapUsedBytes": 164307812,
"domNodes": -8312,
"jsHeapTotalBytes": -8589312,
"scriptDurationMs": 938.346,
"eventListeners": -16383,
"totalBlockingTimeMs": 569,
"frameDurationMs": 17.776666666666642,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "workflow-execution",
"durationMs": 452.48800000001665,
"styleRecalcs": 14,
"styleRecalcDurationMs": 17.991,
"layouts": 2,
"layoutDurationMs": 0.43899999999999995,
"taskDurationMs": 108.353,
"heapDeltaBytes": 5306344,
"heapUsedBytes": 70146232,
"domNodes": 136,
"jsHeapTotalBytes": 4980736,
"scriptDurationMs": 9.65,
"eventListeners": 99,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "workflow-execution",
"durationMs": 453.75300000000607,
"styleRecalcs": 12,
"styleRecalcDurationMs": 19.142,
"layouts": 2,
"layoutDurationMs": 0.3570000000000001,
"taskDurationMs": 111.422,
"heapDeltaBytes": 5074320,
"heapUsedBytes": 69724224,
"domNodes": 121,
"jsHeapTotalBytes": 4718592,
"scriptDurationMs": 10.07,
"eventListeners": 97,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
}
]
} |
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 39 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the 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 configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThe release sheriff now emits sanitized degraded-run details through GitHub Actions outputs. The workflow detects new failures, posts details and the run URL to Slack, and ignores notification errors. The release process documentation describes this behavior. ChangesRelease sheriff reporting
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant ReleaseSheriffScript
participant GitHubActionsWorkflow
participant SlackAPI
ReleaseSheriffScript->>GitHubActionsWorkflow: Write degraded output
GitHubActionsWorkflow->>GitHubActionsWorkflow: Check previous decisive conclusion
GitHubActionsWorkflow->>SlackAPI: Post failure details and workflow URL
SlackAPI-->>GitHubActionsWorkflow: Return notification result
Possibly related PRs
Suggested reviewers: Important Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (1 inconclusive)
✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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 `@scripts/release-sheriff/release-sheriff.ts`:
- Around line 329-339: Update the unmapped-email diagnostic loop to use
emailKey(email) instead of the raw email when constructing the warning message,
while preserving the actionable Datadog tag format and existing problems
handling.
- Around line 293-296: Update output to generate a delimiter that does not occur
in value, and use it for the GITHUB_OUTPUT heredoc instead of the fixed __EOF__
marker. Add a regression test covering value "before\n__EOF__\nafter" and verify
the complete value is emitted as one output.
🪄 Autofix
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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: c920eb6b-1280-455b-b6b1-4f72479b63d2
📒 Files selected for processing (3)
.github/workflows/pr-assign-release-sheriff.yamldocs/release-process.mdscripts/release-sheriff/release-sheriff.ts
Codecov Report✅ All modified and coverable lines are covered by tests. @@ Coverage Diff @@
## main #14735 +/- ##
==========================================
- Coverage 79.51% 78.60% -0.92%
==========================================
Files 1795 1796 +1
Lines 116642 109500 -7142
Branches 34027 30569 -3458
==========================================
- Hits 92751 86067 -6684
+ Misses 23336 22922 -414
+ Partials 555 511 -44
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
Two review findings on the step output feeding the Slack alert. A heredoc output ends at the first line equal to its delimiter, so a value carrying that line would close the record early and let the remainder parse as further outputs. These messages are one line by construction, so collapse them to one line rather than picking a delimiter and hoping it never collides. The unmapped-user warning also carried a full email address into what is a public repository's Actions log, and now a Slack message. The local part is what the Datadog tag needs anyway, so report that instead.
if: failure() fires for any earlier step too, so a checkout or pnpm hiccup would page the rotation for something that is ordinary CI noise, already visible in the run list, and not theirs to fix. Alert fatigue is how the original signal got ignored; a channel that cries wolf gets muted. Scope the condition to the sheriff step's own outcome.
The job runs hourly, so a lasting breakage would have posted to #frontend-releases around the clock until someone fixed it. A channel that cries wolf gets muted, which is the exact failure this alert exists to prevent — the previous version traded under-alerting for over-alerting. Alert only when the last run that decided anything did not already fail. Skipped runs do not count: the pull_request_target gate produces them in bulk (34 of the last 40 runs), so without that filter the previous conclusion would almost always be "skipped" and nothing would ever be throttled. The check fails open — if it cannot read the run history the alert still goes out, because a duplicate beats a silence.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
docs/release-process.md (1)
92-97: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winScope the documentation to sheriff-step failures.
The workflow does not post for every failed run. It posts only when
steps.sheriff.outcome == 'failure'. Name theAssign release sheriffstep so operators do not expect alerts for checkout or setup failures.Suggested wording
-A failed run also posts to **`#frontend-releases`** with the reason, because a +If the **Assign release sheriff** step fails, the workflow also posts to **`#frontend-releases`** with the reason, because a🤖 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 `@docs/release-process.md` around lines 92 - 97, Update the release-process documentation to state that the Slack notification occurs only when the “Assign release sheriff” step fails, rather than for any failed workflow run. Name the `Assign release sheriff` step explicitly and clarify that checkout, setup, and other failures do not trigger this alert.
🤖 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 @.github/workflows/pr-assign-release-sheriff.yaml:
- Around line 74-79: Update the PREVIOUS lookup in the workflow to identify the
prior completed run through paginated workflow-runs results rather than relying
on a fixed per_page=40 response. For the selected previous run, query the
workflow-jobs API and use the conclusion of the “Assign release sheriff” step
for deduplication, instead of using the overall workflow run conclusion;
preserve the “none” fallback when no prior decisive step result exists.
---
Outside diff comments:
In `@docs/release-process.md`:
- Around line 92-97: Update the release-process documentation to state that the
Slack notification occurs only when the “Assign release sheriff” step fails,
rather than for any failed workflow run. Name the `Assign release sheriff` step
explicitly and clarify that checkout, setup, and other failures do not trigger
this alert.
🪄 Autofix
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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 71b0b260-080b-4f9e-8608-a8e56b1231f0
📒 Files selected for processing (2)
.github/workflows/pr-assign-release-sheriff.yamldocs/release-process.md
A run that died in checkout has conclusion "failure" without ever reaching the sheriff. Treating that as "already alerted" would suppress the next genuine sheriff failure — turning a noise fix into a silence bug, which is the failure this alert exists to prevent. Read the conclusion of the "Assign release sheriff" step itself, walking recent scheduled runs. Scheduled runs are used because the pull_request_target gate skips most others, so they are the ones dense in runs that decided anything; that also removes the pagination concern, since the loop stops at the first decisive run rather than hoping one falls inside a fixed page.
benceruleanlu
left a comment
There was a problem hiding this comment.
The files that this touches have been growing in slop recently. I might do a follow-up PR just to clean everything up, but Fable should find the slop issues if you do ask AI. I just wouldn't recommend the GPT models for this cleanup
…omfy-Org#14776) Follow-up to Comfy-Org#14626. Third in the series with Comfy-Org#14735 and Comfy-Org#14766. `planActions` skipped the review request when the sheriff had authored the PR: ```ts pr.author?.login.toLowerCase() !== normalizedSheriffLogin && ``` The guard is necessary — GitHub 422s a self-review request — but the job still *assigned* them, so the PR ended up owned by its own author with **nobody asked to review**. Backport merges are gated on an approval, so it then waited indefinitely on a review that had never been requested. Silent, and shaped exactly like the bug this script was fixed for. ## Fix Request the **next person in the rotation** instead. The order comes from the Datadog layer's member list, which the schedule call already returns for the tags — one extra `include` parameter, no new config, no second source of truth to drift. Verified against the live schedule: ``` rotation: dante01yoon → benceruleanlu → drjkl → austinmroz → huang47 → codejuggernaut → christian-byrne sheriff : benceruleanlu standby: drjkl ``` Wrap-around confirmed: `christian-byrne` → `dante01yoon`. ## Notes - Members with no `github:` tag are dropped from the rotation rather than guessed at, so an unmapped person is skipped as a standby instead of producing a bad request. - If nobody can stand in — a one-person rotation, or a sheriff resolved via `fallbackGithubLogin` and so absent from it — the run warns rather than staying quiet. It does not fail: a sheriff was still resolved and the PR still has an owner. - `SheriffAction` gains a `reviewer` field, so the assignee and the reviewer are no longer assumed to be the same person. - I did **not** add a random fallback. It only becomes reachable when the rotation cannot be read, which means Datadog is degraded — and that path already falls back and exits non-zero. ## Verification 29 tests, including rotation order preservation, wrap-around, case-insensitivity, unmapped members dropped, and the sheriff's-own-PR path. Lint, knip, typecheck, format clean. Note the pre-existing behaviour this does not change: drafts are still skipped, and existing assignees and review requests are still never overwritten.
…-Org#15008) ## Summary The release-sheriff degradation alert posted five times in nine minutes today; only scheduled runs alert now, because only scheduled runs are read back when deciding whether the failure is already known. ## Changes - **What**: gate both `Check whether this failure is already known` and `Report a degraded run to Slack` on `github.event_name == 'schedule'`, and document why. The de-duplication added in Comfy-Org#14735 alerts on the *transition* into failure: it walks recent runs, reads the `Assign release sheriff` step conclusion, and stays quiet if the previous decisive run already failed. That lookup is filtered to `event=schedule` — deliberately, since the `pull_request_target` gate skips most other runs and they would otherwise crowd out the ones that decided anything. But the alert itself fired from *every* run. So a `pull_request_target` failure compared itself only against scheduled history and never against the four other PR-triggered failures minutes earlier: | run | event | slack | | --- | --- | --- | | [31418302878](https://github.com/Comfy-Org/ComfyUI_frontend/actions/runs/31418302878) | pull_request_target | posted | | [31418516631](https://github.com/Comfy-Org/ComfyUI_frontend/actions/runs/31418516631) | pull_request_target | posted | | [31418702868](https://github.com/Comfy-Org/ComfyUI_frontend/actions/runs/31418702868) | pull_request_target | posted | | [31419097641](https://github.com/Comfy-Org/ComfyUI_frontend/actions/runs/31419097641) | pull_request_target | posted | | [31419966276](https://github.com/Comfy-Org/ComfyUI_frontend/actions/runs/31419966276) | schedule | posted | | everything after | either | suppressed | The last one is the transition check working exactly as designed — once a *scheduled* run had failed, the next nine failures stayed quiet. The set that alerts and the set that gets read back have to be the same set. ## Review Focus The trade-off is alerting latency: a breakage that starts right after a sweep is now announced up to an hour later, on the next `23 * * * *` run. PR-triggered runs still fail red on the PR, so the signal is not lost, only the Slack post is delayed. The alternative — widening the lookup to all events — needs deep pagination past the long runs of skipped `pull_request_target` entries to find anything decisive, which fails open into exactly the spam this removes. Trigger for today's burst was a rotation member without a `github:<user>:<login>` tag on the Datadog schedule; that tag is now added, and [this run](https://github.com/Comfy-Org/ComfyUI_frontend/actions/runs/31433830151) is green. Co-authored-by: Connor Byrne <c.byrne@comfy.org>
Follow-up to #14626.
That PR made the sheriff job exit non-zero when it cannot resolve the on-call user. But a failing scheduled workflow only notifies whoever last pushed to
main— in practice nobody. That is exactly how the placeholder Datadog config survived for weeks: every run warned, and every run still reported success.This posts the failure to #frontend-releases (
C09K9TPU2G7), whose channel purpose is literally "Current Release Sheriff".The script writes why it degraded to a step output, so the alert is actionable without opening the run:
Both lookups hit the same API, so an outage or credentials failure produced the same warning twice; deduped so the alert reads once.
The post is
continue-on-errorand follows the existing pattern inpublish-design-system-on-merge.yaml(sameSLACK_BOT_TOKENsecret, samechat.postMessage+jq -e '.ok == true'shape), so Slack being unreachable never masks the underlying result.Verification
Ran the real script both ways:
GITHUB_OUTPUT, no PRs mutatedTests 24/24; lint, format, typecheck clean.