Skip to content

ci: add PR hygiene — UNREVIEWED label + Slack review reminders - #12

Open
severindemchuk wants to merge 2 commits into
masterfrom
pr-hygiene
Open

ci: add PR hygiene — UNREVIEWED label + Slack review reminders#12
severindemchuk wants to merge 2 commits into
masterfrom
pr-hygiene

Conversation

@severindemchuk

@severindemchuk severindemchuk commented Jul 13, 2026

Copy link
Copy Markdown

Summary

  • New PRs (org-wide, once repos adopt templates/pr-label.yml) get the UNREVIEWED label automatically. Reviewers remove it manually after reviewing — that removal is the "reviewed" acknowledgment, automation never touches it again.
  • A weekday-morning cron (pr-reminder.yml) DMs requested reviewers (or the author, if none requested) on Slack about PRs still carrying the label. Nag 1 the next weekday, daily, hard stop after 3.
  • Dogfooding: this repo's own pr-label.yml should label this very PR.

Config needed before the reminder cron can run for real (see follow-up)

  • Actions vars: GH_SLACK_MAP, PR_HYGIENE_DRY_RUN, PR_HYGIENE_ALLOWLIST
  • Secrets: PR_BOT_PAT, SLACK_BOT_TOKEN

Test plan

  • scripts/pr_reminder.py unit tests (kept local for now, not part of this diff)
  • Live dry-run against the org (read-only) — correctly found and evaluated existing UNREVIEWED PRs
  • This PR should get the UNREVIEWED label automatically on open
  • Manually removing the label should stick (nothing re-adds it)

🤖 Generated with Claude Code

New PRs get the UNREVIEWED label via a reusable workflow (consumers copy
templates/pr-label.yml); reviewers remove it manually after reviewing.
A weekday-morning cron DMs reviewers/authors on Slack about PRs still
carrying the label (nag 1-3, then silent). Dry-run and allowlist phases
via Actions variables; PAT now, GitHub App swap planned.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 13, 2026 07:52
@github-actions github-actions Bot added the UNREVIEWED No review yet — remove this label after reviewing label Jul 13, 2026

Copilot AI 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.

Pull request overview

Adds organization-wide PR hygiene automation by applying an UNREVIEWED label to new PRs and sending weekday Slack DM reminders until the label is manually removed.

Changes:

  • Introduces a reusable workflow (plus template + local “dogfooding” workflow) to label PRs as UNREVIEWED on open/reopen.
  • Adds a scheduled GitHub Actions workflow that runs a Python script to find UNREVIEWED PRs and DM the appropriate people on Slack.
  • Adds a Slack app manifest to document required Slack bot setup/scopes.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
templates/pr-label.yml Template workflow to apply UNREVIEWED label in adopting repos
scripts/pr_reminder.py Implements GitHub search + nag calculation + Slack DM sending
docs/slack-app-manifest.yml Documents Slack app configuration/scopes for the reminder bot
.github/workflows/reusable-pr-label.yml Reusable workflow that ensures the label exists and applies it
.github/workflows/pr-reminder.yml Cron/dispatch workflow wiring env/secrets and running the reminder script
.github/workflows/pr-label.yml Dogfooding workflow to label PRs in this repo

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/pr-reminder.yml
Comment thread .github/workflows/pr-reminder.yml
Comment thread .github/workflows/pr-reminder.yml
Comment thread templates/pr-label.yml
Comment thread .github/workflows/pr-label.yml
Comment thread scripts/pr_reminder.py Outdated
Comment thread scripts/pr_reminder.py Outdated
- pr-reminder.yml declared explicit permissions, which zeroes out any
  unlisted scope — actions/checkout needs contents: read to work.
- pr_reminder.py: bound GitHub/Slack urlopen() calls with a timeout so a
  hung connection can't stall the whole workflow run.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 13, 2026 08:20

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

name: PR label
on:
pull_request:
types: [opened, reopened]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

So ist es vermutlich einfacher, als erst beim Merge das Label hinzuzufügen. Dann aber bitte auch das Label automatisch entfernen, wenn der PR approved wird: https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#pull_request_review

env:
GH_TOKEN: ${{ github.token }}
run: |
gh api "repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/labels" \

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Warum ist das issues? Unterscheidet die REST API nicht zwischen issues und PRs?

GH_TOKEN: ${{ github.token }}
run: |
gh api "repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/labels" \
-f "labels[]=UNREVIEWED"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Werden so alle bestehenden Labels überschrieben? Oder ist das ein append?

Comment thread templates/pr-label.yml

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Ich denke es reicht, wenn man es aus .github/actions kopieren kann. Sonst geraten die Files früher oder später out of sync.

Comment thread scripts/pr_reminder.py


def search_unreviewed_prs(org, token):
query = f"org:{org} is:pr is:open label:{LABEL}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Es müsste (is:open OR label:UNREVIEWED) sein. Mir geht es ja vor allem darum, das Reviews nachgeholt werden, wenn (z.B. hotfixes) bereits gemergt wurde.

Comment thread scripts/pr_reminder.py
GITHUB_API = "https://api.github.com"
SLACK_API = "https://slack.com/api/chat.postMessage"
LABEL = "UNREVIEWED"
MAX_NAGS = 3

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Ich würde es glaube ich lieber 1-mal pro Woche machen und dafür kein Limit. Das ein PR ein paar Tage rumliegt, kann schonmal passieren und da soll man nicht unbedingt genervt werden. Es soll eigentlich nur verhindert werden, dass man PRs ganz vergisst.

Comment thread scripts/pr_reminder.py


def pr_targets(repo, number, author, token):
"""(logins, is_author_fallback) — requested reviewers, else the author."""

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Ich würde assignee -> reviewer -> author als Fallback Reihenfolge nehmen. Ich arbeite z.B. so, dass ich den PR dem Author zurück assigne, wenn ich findings habe. Dann macht es keinen Sinn, wenn ich nochmal benachrichtigt werde.

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

Labels

UNREVIEWED No review yet — remove this label after reviewing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants