Skip to content

Replace per-merge Slack messages with a daily PR dashboard#1448

Merged
mmkal merged 10 commits into
mainfrom
slack-daily-pr-dashboard
Jun 10, 2026
Merged

Replace per-merge Slack messages with a daily PR dashboard#1448
mmkal merged 10 commits into
mainfrom
slack-daily-pr-dashboard

Conversation

@mmkal

@mmkal mmkal commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Replaces the merge-to-main-slack workflow (one Slack message per merged PR — noisy on busy days) with a workflow that maintains at most one message per day in #ci: a one-line PR dashboard summary, with the full per-PR breakdown in a single threaded reply. Both are created on the first PR event of the day and updated in place after that.

Channel message:

PR dashboard 10th June — 51 merged · 9 closed without merging · 4 opened · 2 older still open (details in thread)

Threaded reply (rendered from real data):

Merged:
#1410 Fix 5-min logout, deploy-time JWKS, and stream append skeleton flash by jonas (ad6da76)
#1407 itx: contexts, capabilities, and the one true handle by jonas (f256768)

Closed without merging:
#1440 Migrate captun to published npm 0.0.3 by misha

Opened:
#1448 Replace per-merge Slack messages with a daily PR dashboard by misha (draft)

Old: #1349, #1355

How it works:

  • Content is refetched from the GitHub search API on every run (merged / closed-unmerged / opened-and-still-open today, plus older open PRs), so the message is self-healing — no incremental state to corrupt.
  • The day's message timestamps live in a repo Actions variable (SLACK_PR_DASHBOARD_STATE, {date, channel, ts, details_ts}), written with the same ITERATE_BOT_GITHUB_TOKEN the nag workflow uses. No new Slack scopes needed: chat.update uses the chat:write the bot already exercises.
  • Targets #ci, adopting [codex] Route merge announcements to ci #1452's decision to move merge announcements out of #building (that PR edited the workflow this one deletes; the conflict is resolved here by keeping the deletion).
  • The threaded details go out as chunked mrkdwn section blocks rather than one text param: on busy days a single text field hits chat.update's msg_too_long (postMessage truncates, update rejects — found by e2e-testing against today's ~50 merges).
  • Plain-text author names (no @-mentions) since the messages update many times a day.
  • Testable two ways: pushing any *pr-dashboard* branch runs it for real against #misha-test with a separate state variable (create, update-in-place, and threading paths all verified this way — e.g. runs 27280068182, 27288814028), and node cli.ts github-script pr-dashboard.update_dashboard.update_pr_dashboard --github-token ... does a local dry run that prints both messages.

Task file: tasks/slack-daily-pr-dashboard.md.

🤖 Generated with Claude Code


Note

Low Risk
CI/Slack automation only; no app auth or production runtime changes, with test channel and dry-run paths.

Overview
Removes the per-merge Slack workflow and replaces it with a daily PR dashboard in #ci: one parent message per UTC day with count-only summary, full lists in a single threaded reply, both updated in place on PR open/close/reopen/ready events.

The new workflow queries GitHub search (merged, closed-unmerged, opened-today still open, older open PRs), maps authors via existing slackUsers, and persists parent/thread ts in repo Actions variables (SLACK_PR_DASHBOARD_STATE) using ITERATE_BOT_GITHUB_TOKEN. Thread details use chunked mrkdwn blocks to avoid chat.update msg_too_long; concurrency group prevents double-posts. Branches matching *pr-dashboard* post to #misha-test for e2e testing; local github-script dry-runs when the Slack secret is unexpanded.

Adds tasks/slack-daily-pr-dashboard.md documenting design and rollout.

Reviewed by Cursor Bugbot for commit 5b1c341. Bugbot is set up for automated code reviews on this repo. Configure here.

mmkal and others added 10 commits June 10, 2026 14:22
The merge-to-main-slack workflow posts one message per merged PR, which
is noisy. Spec out a replacement that maintains a single per-day
dashboard message in #building, updated in place on PR events.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One message per UTC day in #building, created on the first PR event of
the day and updated in place after that (chat.update). Content is
refetched from the GitHub search API each run: merged / closed-unmerged
/ opened today, plus a compact line of older still-open PRs. The
message ts lives in a repo Actions variable; pushes to *pr-dashboard*
branches exercise the workflow against #misha-test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…/iterate into slack-daily-pr-dashboard

# Conflicts:
#	tasks/slack-daily-pr-dashboard.md
GitHub rejects the whole workflow file as malformed if the script
contains an unclosed ${{ sequence, which the local dry-run detection
did. Detect the unexpanded secret by its name instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The e2e run on today's (busy) PR list updated fine on post but failed
on update: postMessage truncates long text, chat.update rejects it,
and the fallback then posted a second message - the noise problem all
over again. Chunk lines into 2900-char mrkdwn section blocks instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…shboard; #1452's #ci routing adopted by pointing the dashboard at #ci)
The full per-PR breakdown was huge in-channel on busy days. The
channel message is now a one-line summary with counts; the breakdown
lives in a single threaded reply, both updated in place (parent update
passes blocks: [] since chat.update retains existing blocks otherwise).

Channel moves from #building to #ci, adopting #1452's routing decision
for merge announcements (merged from main; the old workflow it edited
stays deleted).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@mmkal

mmkal commented Jun 10, 2026

Copy link
Copy Markdown
Contributor Author
image

@mmkal mmkal marked this pull request as ready for review June 10, 2026 17:19
@mmkal mmkal merged commit d55454c into main Jun 10, 2026
6 checks passed
@mmkal mmkal deleted the slack-daily-pr-dashboard branch June 10, 2026 17:19

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 5b1c341. Configure here.

per_page: 100,
advanced_search: "true",
});
return data.items;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Search capped at hundred results

Medium Severity

Each dashboard refresh loads PR lists via issuesAndPullRequests with per_page: 100 and returns only data.items, with no pagination or total_count check. When more than 100 PRs match a bucket (merged today, closed unmerged, opened today, or older open), the Slack summary counts and thread lists silently omit the rest.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 5b1c341. Configure here.

const message = await slack.chat.postMessage({ channel, text: summaryText });
if (!message.ts) throw new Error(`No ts in postMessage response`);
const detailsTs = await postDetailsInThread(message.ts);
await writeState({ date: today, channel, ts: message.ts, details_ts: detailsTs });

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Slack post before state save

Medium Severity

After posting or re-posting Slack messages, the workflow persists SLACK_PR_DASHBOARD_STATE only in writeState. If writeState fails after a successful postMessage, the job errors but Slack already has the new parent or thread reply while the variable still lacks the matching ts / details_ts. The next PR-triggered run treats the day as uninitialized or stale and can post another dashboard parent or thread reply for the same UTC day.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 5b1c341. Configure here.

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