Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions .github/discord-bot/github.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,6 @@ async function listIssues(owner, repo, query) {
return out
}

export async function listOpenIssues(owner, repo) {
return listIssues(owner, repo, 'state=open')
}

/** Every issue filed against one milestone — closed ones included, for the ratio. */
export async function listMilestoneIssues(
owner,
Expand Down
58 changes: 0 additions & 58 deletions .github/discord-bot/handlers/issues.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -59,61 +59,6 @@ async function announceUnblocked(owner, repo, issue, { trigger, block }) {
})
}

/** Someone got assigned — tell them whether they can actually start. */
async function onAssigned(owner, repo, issue, payload) {
const target = payload.assignee?.login
const block = await getBlockState(owner, repo, issue)
const blocking = await countBlocking(owner, repo, issue.number)

const blockingField = {
name: 'Blocking',
value: blockingFieldValue(blocking),
inline: true,
}

if (!block.blocked) {
const urgency = blocking
? ` Worth prioritising — it's ${blockingPhrase(blocking)}.`
: ''
await sendDiscord({
content: `${mention(target)} — you're assigned to #${issue.number} and nothing is blocking it. Ready to work.${urgency}`,
pingLogins: [target],
embed: {
title: `#${issue.number} ${clamp(issue.title, 200)}`,
url: issue.html_url,
color: COLORS.ready,
description: clamp(issue.body, 300) || '_No description._',
fields: [
blockingField,
{ name: 'Repo', value: `${owner}/${repo}`, inline: true },
],
timestamp: new Date().toISOString(),
},
})
return
}

await sendDiscord({
content: `${mention(target)} — you're assigned to #${issue.number}, but it's blocked. Nothing to do yet; I'll ping you the moment it clears.`,
pingLogins: [target],
embed: {
title: `#${issue.number} ${clamp(issue.title, 200)}`,
url: issue.html_url,
color: COLORS.blocked,
fields: [
{
name: 'Waiting on',
value: block.openBlockers.length
? clamp(formatBlockerList(block.openBlockers), 800)
: 'a blocking label',
},
blockingField,
],
timestamp: new Date().toISOString(),
},
})
}

/** A closed issue can free everything downstream of it. */
async function onClosed(owner, repo, issue) {
const dependents = await findDependents(owner, repo, issue.number)
Expand All @@ -136,9 +81,6 @@ export async function handleIssues(payload) {
const repo = repository.name

switch (action) {
case 'assigned':
return onAssigned(owner, repo, issue, payload)

case 'closed':
return onClosed(owner, repo, issue)

Expand Down
22 changes: 6 additions & 16 deletions .github/discord-bot/handlers/pull_request.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -141,34 +141,24 @@ export async function handlePullRequest(payload) {
}
}

/** A submitted review is news for the PR author, not the reviewer. */
/** A request for changes is news for the PR author, not the reviewer. */
export async function handlePullRequestReview(payload) {
if (payload.action !== 'submitted') return

const { review, pull_request: pr, repository } = payload
// Approvals and plain comments are not announced; only requested changes are.
if (String(review.state ?? '').toLowerCase() !== 'changes_requested') return

const author = pr.user?.login
const reviewer = review.user?.login

const line = {
approved: {
text: `${mention(author)} — ${mention(reviewer)} approved #${pr.number}. Good to merge.`,
color: COLORS.unblocked,
},
changes_requested: {
text: `${mention(author)} — ${mention(reviewer)} requested changes on #${pr.number}.`,
color: COLORS.review,
},
}[String(review.state ?? '').toLowerCase()]

if (!line) return // plain comments would just be noise

await sendDiscord({
review: true,
content: line.text,
content: `${mention(author)} — ${mention(reviewer)} requested changes on #${pr.number}.`,
// The reviewer is pinged as well as the author: they asked for a change and will
// want the thread in their notifications when the revision lands.
pingLogins: [...new Set([author, reviewer].filter(Boolean))],
embed: prEmbed(pr, repository, line.color, [
embed: prEmbed(pr, repository, COLORS.review, [
{
name: 'Review',
value: clamp(review.body, 500) || '_No comment left._',
Expand Down
143 changes: 0 additions & 143 deletions .github/discord-bot/reminders.mjs

This file was deleted.

3 changes: 2 additions & 1 deletion .github/workflows/discord-notify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ name: Discord notifications

on:
issues:
types: [assigned, closed, unlabeled, edited]
# No `assigned` on purpose: taking an issue is not announced on Discord.
types: [closed, unlabeled, edited]
# pull_request_target (not pull_request) so notifications also work for PRs opened
# from forks, which are not given access to secrets. Safe here because the job only
# ever runs code from the base branch — it never checks out the PR's own code.
Expand Down
19 changes: 1 addition & 18 deletions .github/workflows/discord-reminders.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,10 @@ name: Discord reminders
on:
schedule:
# 13:00 UTC = 09:00 Montreal (EDT) / 08:00 (EST), every second day of the month.
# Carries two digests: work that has gone quiet, and sprints past their due date.
# Chases sprints past their due date.
- cron: '0 13 */2 * *'
# Lets you run it on demand from the Actions tab without waiting for the schedule.
workflow_dispatch:
inputs:
stale_days:
description: 'Remind about issues with no activity for this many days'
required: false
default: '2'

permissions:
issues: read
Expand All @@ -29,19 +24,7 @@ jobs:
fetch-depth: 1
persist-credentials: false

- name: Send reminder digest
run: node .github/discord-bot/reminders.mjs
env:
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
DISCORD_USER_MAP: ${{ secrets.DISCORD_USER_MAP }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
STALE_DAYS: ${{ inputs.stale_days || '2' }}
BLOCKED_LABELS: blocked

# Runs even if the digest above failed: the two are independent, and a late
# sprint is exactly the thing you do not want silently dropped.
- name: Chase overdue sprints
if: always()
run: node .github/discord-bot/sprint.mjs
env:
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
Expand Down
Loading