feat(release-bot): scheduled Discord announcements for releases and videos - #282
Open
Anmol-Baranwal wants to merge 3 commits into
Open
Anmol-Baranwal wants to merge 3 commits into
Anmol-Baranwal wants to merge 3 commits into
Conversation
Posts new GitHub releases and YouTube videos into the CopilotKit, AG-UI and OpenBot channels. Runs as a Railway cron job. Release notes are not forwarded. Each release is paired with the commits since the previous one and rewritten into a few lines about what changed, with outside contributors credited by name. There is no state file. Every announcement ends with its source URL, so the bot reads its own recent messages to find what it has already posted and announces only what is newer, oldest first. Running twice posts nothing the second time, and a crash mid-batch cannot cause a repeat. Sources are configured in src/sources.ts, one entry per repository, with the tag filter and the reason for it written together. Adding a repo is an entry there and a channel id in the environment. Covered by 75 tests across the watermark, the 2000-character budget, the GitHub and YouTube parsing, and the summarizer's skip handling.
- read channel history far enough back to cover the release window - treat out-of-credit, truncated and unrecognised OpenAI errors as what they are, instead of retrying forever or giving up permanently - keep reading compare pages after one fails and never skip a release based on a partial commit list - bump Node past the corepack version that fails the Docker build
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Posts CopilotKit, AG-UI and OpenBot releases to their Discord channels, plus new videos from the CopilotKit YouTube channel. Runs once a day on Railway.
Release notes are not postable as they are. AG-UI's are pages of package tables, CopilotKit's are often one sentence. So the bot sends the notes and the recent commits to OpenAI and gets back a few lines on what actually changed.
How it works
sources.tsis the whole config surface. One entry per repo: which repo, which channel, which role to ping, which tags count, and how to title the post. Adding a repo is an entry there plus a channel id in the env. Tag filters live in code rather than env because they are decisions about what is worth announcing, and they need a reason written next to them. That is also what keeps junk likepr-6517-visualsandvundefinedout of the channel.The rest is
github.ts(read releases and the commits between two of them),youtube.ts(the channel feed),summarize.ts(the OpenAI call and what to do when it fails),discord.ts(read channel history, post),watermark.ts(what is still pending), andindex.tswiring it together.No database. Every message it posts ends with the release URL, so to know what it has already announced it reads its own recent messages in the channel and looks at those URLs. The channel is the truth. If it is in there, it went out. Delete a message and it gets posted again, which is handy. Nothing to migrate if a repo moves.
It posts what is not in the channel yet, rather than what shipped since the last run, because there is no record of when the last run was. The 30 day window is the catch-up range: if a run fails, or the service is down for a couple of days, the next run picks up what it missed. On a normal day nothing is new and it posts nothing.
That is also why it has to read channel history back past 30 days. If it read less, a release could be too old for the bot to see its own announcement but still inside the window, so it would get posted again every day.
CopilotKit also ships
v1.73.0,channels/v0.11.0andangular/v0.5.2from the same repo. Those are separate release lines, so the bot tracks them separately. Otherwise postingv1.73.0makes it think everything older is done, and achannels/release from an hour earlier gets skipped.Each release is its own message, oldest first, at most 2 per source per run, so a backlog catches up over a few days instead of dumping into the channel at once.
First run in a channel
Say you point it at a channel that has nothing from it yet. It does not replay the last 30 days. It posts the current version of each thing the repo ships, and nothing older.
For CopilotKit that is three messages: the latest CopilotKit release, the latest Channels SDK release and the latest Angular SDK release. Those go out over two days, since it posts at most two per run. AG-UI and OpenBot each ship one thing, so they get one message.
After that it is caught up and stays quiet until something new ships.
A new channel should not get a month of history dumped into it, and it should not be silent about what the current version is either.
What it does when things go wrong
Bot was off for a while. Picks up where it left off, 2 per source per run, oldest first. Anything that aged past 30 days while it was down is not posted.
A release will not summarize. Temporary failure, it holds that source in place and tries again next run, so nothing jumps the queue. If the release itself is the problem, it posts the link with no summary rather than blocking everything behind it. If the key or model is wrong it stops the run and says so, instead of filling the channel with "Summary unavailable" and losing those releases for good.
A message gets deleted. That release gets posted again next run. The channel is the record, so this is how you force a repost.
Nothing actually shipped. Releases that are only dependency bumps, CI or version metadata get skipped. It checks that against the commits rather than taking the model's word for it.
Open questions for review
sources.tsare my read of what is worth announcing.intelligence-*, the per-adapterchannels-teams/lines andpython-sdk/are all skipped. Say if any of those should go out.One shared file changed
.dockerignoreis repo wide, so this is the one change that is not scoped to the new app.Docker only applies a rule at the top level unless it starts with
**/. The old.env*line therefore covered the root.envand nothing else, soapps/release-bot/.envandapps/discord-mcp/.envwere both being uploaded into the build context.Neither reached a shipped image, since every final stage copies only build output, but they should not have been going at all. The rules now match at any depth. The only tracked files affected are the three
.env.examplefiles, and those are added back on the next line. Other services are unaffected: they all build from inside Docker and none of them read host build output.Happy to pull this into a separate PR if you would rather keep this one scoped.
Tested
199 tests, covering how it reads a channel to work out what it already posted, tracking each product separately, deciding what is still owed, tag filtering, what it does on each kind of OpenAI failure, building a message and trimming it to fit, retries and rate limits on Discord and GitHub, and parsing the YouTube feed.
Also ran it live against a test Discord server: posted, held the rest back, went quiet once caught up, and re-posted a release after its message was deleted.
The README covers setup: env vars, the Discord permissions it needs and why, the dry run flag, the full list of what is announced and what is skipped, and the Railway config.