Skip to content

Commit c7785f3

Browse files
authored
[HDX-4666] Add OSS release reminder workflow (#2557)
## Summary OSS releases are automated end-to-end by [changesets](https://github.com/changesets/changesets) + `.github/workflows/release.yml`: a push to `main` opens/updates an auto-generated **"Release HyperDX"** version-bump PR, and merging that PR is what actually cuts the release (publishes the npm packages, CLI binaries, and multi-arch Docker images, then fires the downstream syncs). The catch: **merging that Release PR is a manual step**, and it's easy to forget. That's how the last OSS release slipped ~a month — the community noticed in #observability that releases had stalled while changesets piled up (HDX-4666). This PR adds a safety net. It deliberately does **not** rebuild the publish pipeline (already exists) and does **not** auto-merge the Release PR (we keep the human review gate on the version bump). **Change:** - **`.github/workflows/release-reminder.yml`** — a scheduled workflow (Friday 20:00 UTC = 12pm PST / 1pm PDT) plus `workflow_dispatch`. It queries open PRs (read-only, no checkout) and, if an unmerged **"Release HyperDX"** PR is open, posts to **#hyperdx-pull-requests** with the PR link, how long it's been open, and a merge nudge — escalating the wording to "overdue" once it's been pending more than 7 days, and `@`-mentioning the release owner (via the `RELEASE_SLACK_MEMBER_ID` repo/org variable) so they get notified. If no Release PR is open, it stays silent. Reuses the existing `SLACK_WEBHOOK_OSS_PRS` secret and mirrors the conventions in `external-contributor-alerts.yml` (fail-soft, JSON-escaped payloads). No changeset is included: this is a CI workflow change with no published-package behavior change (exempt per `AGENTS.md`). ### Setup required Set the `RELEASE_SLACK_MEMBER_ID` repo variable to the release owner's Slack member ID so the reminder `@`-mentions them (leave unset to skip the mention). Already configured on this repo. ### How to test on Vercel preview N/A — non-UI change (CI workflow only). ### References - Linear Issue: [HDX-4666](https://linear.app/clickhouse/issue/HDX-4666/automate-the-oss-release-process-or-notify-hyperdx-pull-requests-so) - Related PRs: ### Testing notes - Workflow YAML validated (parses cleanly) and is Prettier-compliant. - Live Slack delivery can be verified after merge via the workflow's `workflow_dispatch` trigger.
1 parent d1802e1 commit c7785f3

1 file changed

Lines changed: 76 additions & 0 deletions

File tree

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
name: Release Reminder
2+
3+
on:
4+
schedule:
5+
- cron: '0 20 * * 5'
6+
workflow_dispatch:
7+
8+
permissions:
9+
pull-requests: read
10+
11+
concurrency:
12+
group: release-reminder
13+
cancel-in-progress: false
14+
15+
jobs:
16+
remind:
17+
runs-on: ubuntu-latest
18+
steps:
19+
- uses: actions/github-script@v9
20+
env:
21+
SLACK_WEBHOOK_OSS_PRS: ${{ secrets.SLACK_WEBHOOK_OSS_PRS }}
22+
with:
23+
script: |
24+
const MENTION_ID = '${{ vars.RELEASE_SLACK_MEMBER_ID }}';
25+
const RELEASE_PR_TITLE = 'Release HyperDX';
26+
const OVERDUE_DAYS = 7;
27+
28+
const { owner, repo } = context.repo;
29+
30+
const prs = await github.paginate(github.rest.pulls.list, {
31+
owner, repo, state: 'open', per_page: 100,
32+
});
33+
const releasePr = prs.find(pr =>
34+
pr.title === RELEASE_PR_TITLE &&
35+
pr.user?.type === 'Bot' &&
36+
(pr.user?.login === 'github-actions[bot]' || pr.user?.login === 'github-actions')
37+
);
38+
39+
if (!releasePr) {
40+
core.info('No open "Release HyperDX" PR found — nothing pending. Staying silent.');
41+
return;
42+
}
43+
44+
const openedAt = new Date(releasePr.created_at);
45+
const daysOpen = Math.floor((Date.now() - openedAt.getTime()) / 86_400_000);
46+
const overdue = daysOpen >= OVERDUE_DAYS;
47+
48+
const mention = MENTION_ID ? `<@${MENTION_ID}> ` : '';
49+
const header = overdue
50+
? `:rotating_light: *OSS release is overdue* — the Release PR has been open ${daysOpen} day(s).`
51+
: `:package: *OSS release is pending* — a Release PR has been open ${daysOpen} day(s).`;
52+
const text = `${mention}${header}\n`
53+
+ `Merge it to cut the release (publishes Docker/npm/CLI artifacts):\n`
54+
+ `<${releasePr.html_url}|#${releasePr.number}: ${releasePr.title}>`;
55+
56+
const webhook = process.env.SLACK_WEBHOOK_OSS_PRS;
57+
if (!webhook) {
58+
core.warning('SLACK_WEBHOOK_OSS_PRS not set — no reminder sent.');
59+
return;
60+
}
61+
62+
try {
63+
const res = await fetch(webhook, {
64+
method: 'POST',
65+
headers: { 'Content-Type': 'application/json' },
66+
body: JSON.stringify({ blocks: [{ type: 'section', text: { type: 'mrkdwn', text } }] }),
67+
});
68+
if (!res.ok) {
69+
core.setFailed(`Slack post failed (${res.status}).`);
70+
return;
71+
}
72+
} catch (e) {
73+
core.setFailed(`Slack post errored (${e.message}).`);
74+
return;
75+
}
76+
core.info(`Reminder sent for Release PR #${releasePr.number} (open ${daysOpen} day(s)).`);

0 commit comments

Comments
 (0)