-
Notifications
You must be signed in to change notification settings - Fork 5
Push Linear updates to Discord channel #345
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Add logic for webhook management
Did we get you the ability to set these variables in kube? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds functionality to connect and disconnect Linear teams with Discord channels, enabling automated delivery of Linear project updates as custom embeds via webhooks.
- Introduces two new slash commands: "/linear-updates connect team-name" and "/linear-updates disconnect team-name".
- Implements webhook creation and deletion logic with secure header verification.
- Utilizes two new environment variables for configuration.
|
||
const teams = await fetchLinearTeams() | ||
|
||
await application.commands.set([]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clearing all commands here may unintentionally remove commands from other integrations; consider updating or adding only the specific Linear command instead of resetting the entire command list.
Copilot uses AI. Check for mistakes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left a few notes.
} | ||
if (existingConnections[teamId]) { | ||
await interaction.reply({ | ||
content: "⚠️ This Linear team is already connected to a channel.", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless there's a technical limitation, I think it's fine to connect the same team to multiple channels—we just shouldn't connect the same team to the same channel more than once. Wdyt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did some refactoring here so that you can set updates across several channels but still fires the message if you try connecting updates to one that has that specific team + channel already linked ✨
return | ||
} | ||
await interaction.reply({ | ||
content: "Linked this channel", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any chance we can be explicit here? e.g. Now streaming <team name> project updates to this channel
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually is this redundant to the message after succeeding?
}) | ||
|
||
await interaction.editReply({ | ||
content: `Connected Linear team **${team.name}** to this channel and added webhook to Linear`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems a little too technical tbh.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed and added these to debug only!
} | ||
}) | ||
robot.router.post( | ||
/^\/linear-([a-z0-9-]+)-(\d{6})$/, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's use /linear/
and subpath below that? Maybe even /linear/webhook/team/...
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed this around but kept the id pattern at the end so it's /linear/webhook/channel-name-randomId
@coderabbitai full review |
✅ Actions performedFull review triggered. |
WalkthroughA new module was added to integrate Linear project management updates with Discord via a bot. It introduces slash commands for connecting or disconnecting a Linear team to a Discord channel, manages webhook registration and deletion, verifies incoming webhook signatures, and posts formatted project update messages to Discord channels. Persistent storage is used for connection data. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Discord
participant Bot
participant Linear API
participant Brain
User->>Discord: Issues /linear-updates connect/disconnect command
Discord->>Bot: Sends interaction event
Bot->>Linear API: (On connect) Register webhook for team
Bot->>Brain: Store connection details (team, channel, secret)
Bot->>Linear API: (On disconnect) Delete webhook
Bot->>Brain: Remove connection details
Bot-->>Discord: Ephemeral reply to user
sequenceDiagram
participant Linear API
participant Bot
participant Brain
participant Discord Channel
Linear API->>Bot: POST webhook event (with signature)
Bot->>Brain: Retrieve connection by team/channel
Bot->>Bot: Verify HMAC signature
alt Valid signature & ProjectUpdate event
Bot->>Discord Channel: Post formatted project update embed
else Invalid signature or unknown event
Bot->>Bot: Log error, respond with error status
end
Poem
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
discord-scripts/linear-integration.tsOops! Something went wrong! :( ESLint: 8.35.0 Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'prettier' imported from /node_modules/eslint-plugin-prettier/worker.js Note ⚡️ AI Code Reviews for VS Code, Cursor, WindsurfCodeRabbit now has a plugin for VS Code, Cursor and Windsurf. This brings AI code reviews directly in the code editor. Each commit is reviewed immediately, finding bugs before the PR is raised. Seamless context handoff to your AI code agent ensures that you can easily incorporate review feedback. Note ⚡️ Faster reviews with cachingCodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure ✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
♻️ Duplicate comments (3)
discord-scripts/linear-integration.ts (3)
45-48
: URL concatenation is still fragile – trailing-slash bug remainsPast feedback pointed this out and the code remains unchanged. If
VALKYRIE_ROOT_URL
lacks a trailing “/”, the final URL becomes invalid (https://example.comlinear-foo
). Use theURL
constructor or normalise the root first.
(See previous suggestion at line 47.)
97-98
: Resetting all application commands wipes unrelated slash commands
application.commands.set([])
removes every global command before recreating ours. That can break other integrations running in the same bot. Please update only the specific command instead of flushing the entire list.
281-282
: Variable is mis-named (channelId
actually holds a Team ID)The value extracted from
teamsInfo[0].id
is the Linear team identifier, not a Discord channel identifier. The misleading name caused confusion later (seeexistingConnections[channelId]
).
🧹 Nitpick comments (2)
discord-scripts/linear-integration.ts (2)
40-52
: Replaceconsole.*
with the project logger
console.error/log
bypasses our structured logging and also trips the ESLint rule already shown in the pipeline.
Switch torobot.logger
(or whichever logger abstraction we standardise on). Example:- console.error("Webhook creation failed: Channel is not a TextChannel.") + robot.logger.error("Webhook creation failed: Channel is not a TextChannel.") ... - console.log("Generated custom webhook URL:", customWebhookUrl) + robot.logger.info(`Generated custom webhook URL: ${customWebhookUrl}`) ... - console.error("Error generating custom webhook URL:", error) + robot.logger.error("Error generating custom webhook URL:", error)🧰 Tools
🪛 GitHub Check: lint
[warning] 41-41:
Unexpected console statement
[warning] 49-49:
Unexpected console statement
[warning] 52-52:
Unexpected console statement
159-177
: One-channel-per-team restriction is hard-coded
existingConnections[teamId]
keys the persistence by team only, so the same Linear team cannot be streamed to multiple Discord channels (earlier review discussed this). If multi-channel support is acceptable, consider keying byteamId + channelId
or storing an array of channels per team to avoid this limitation while still preventing duplicate entries in a single channel.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting
📒 Files selected for processing (1)
discord-scripts/linear-integration.ts
(1 hunks)
🧰 Additional context used
🪛 GitHub Check: lint
discord-scripts/linear-integration.ts
[warning] 41-41:
Unexpected console statement
[warning] 49-49:
Unexpected console statement
[warning] 52-52:
Unexpected console statement
[warning] 62-62:
Unexpected console statement
Add autocomplete to command for loading team names dynamically.
Fix for a bug when sometimes the channel name isn't properly found on webhook
@Shadowfiend Made some large refactoring here as well as fixing the issues like verbiage on messages, channel mapping, and being able to add the connection to several channels. If it looks good, approve but don't merge as I can get the vars added to our instance 🙌 |
Notes
This adds two new commands which will create a new webhook connection between Linear & Discord in order to send project updates directly to Discord from linear via a custom embed.
Once a channel is connected, Linear will send all Project updates from that specific team to the channel via the webhook call using a secure header with linear-signature that we set during the initial creation. This connection can also be built on to support additional notifications from Linear -> Discord
Adds two new environment variables which need to be defined for the script to load on start
Summary by CodeRabbit
New Features
Bug Fixes