diff --git a/docs/admin/monitoring/notifications/index.md b/docs/admin/monitoring/notifications/index.md index aa54ad9c143dc..a7eeab44d4b79 100644 --- a/docs/admin/monitoring/notifications/index.md +++ b/docs/admin/monitoring/notifications/index.md @@ -3,23 +3,6 @@ Notifications are sent by Coder in response to specific internal events, such as a workspace being deleted or a user being created. -## Enable experiment - -In order to activate the notifications feature on Coder v2.15.X, you'll need to -enable the `notifications` experiment. Notifications are enabled by default -starting in v2.16.0. - -```bash -# Using the CLI flag -$ coder server --experiments=notifications - -# Alternatively, using the `CODER_EXPERIMENTS` environment variable -$ CODER_EXPERIMENTS=notifications coder server -``` - -More information on experiments can be found -[here](https://coder.com/docs/contributing/feature-stages#experimental-features). - ## Event Types Notifications are sent in response to internal events, to alert the affected @@ -267,12 +250,17 @@ To resume sending notifications, execute If notifications are not being delivered, use the following methods to troubleshoot: -1. Ensure notifications are being added to the `notification_messages` table -2. Review any error messages in the `status_reason` column, should an error have - occurred -3. Review the logs (search for the term `notifications`) for diagnostic - information
_If you do not see any relevant logs, set - `CODER_VERBOSE=true` or `--verbose` to output debug logs_ +1. Ensure notifications are being added to the `notification_messages` table. +1. Review any available error messages in the `status_reason` column +1. Review the logs. Search for the term `notifications` for diagnostic information. + + - If you do not see any relevant logs, set + `CODER_VERBOSE=true` or `--verbose` to output debug logs. +1. If you are on version 2.15.x, notifications must be enabled using the + `notifications` + [experiment](../../../contributing/feature-stages.md#experimental-features). + + Notifications are enabled by default in Coder v2.16.0 and later. ## Internals @@ -283,7 +271,7 @@ concurrency. All messages are stored in the `notification_messages` table. -Messages older than 7 days are deleted. +Messages older than seven days are deleted. ### Message States diff --git a/docs/admin/monitoring/notifications/slack.md b/docs/admin/monitoring/notifications/slack.md index 58bf9338ea2ae..e7cad847faad4 100644 --- a/docs/admin/monitoring/notifications/slack.md +++ b/docs/admin/monitoring/notifications/slack.md @@ -17,8 +17,7 @@ consistent between Slack and their Coder login. Before setting up Slack notifications, ensure that you have the following: - Administrator access to the Slack platform to create apps -- Coder platform v2.15.0 or greater with - [notifications enabled](./index.md#enable-experiment) for versions =v2.16.0 ## Create Slack Application @@ -34,9 +33,9 @@ To integrate Slack with Coder, follow these steps to create a Slack application: 3. Under "OAuth & Permissions", add the following OAuth scopes: - - `chat:write`: To send messages as the app. - - `users:read`: To find the user details. - - `users:read.email`: To find user emails. + - `chat:write`: To send messages as the app. + - `users:read`: To find the user details. + - `users:read.email`: To find user emails. 4. Install the app to your workspace and note down the **Bot User OAuth Token** from the "OAuth & Permissions" section. @@ -52,128 +51,130 @@ To build the server to receive webhooks and interact with Slack: 1. Initialize your project by running: - ```bash - npm init -y - ``` + ```bash + npm init -y + ``` 2. Install the Bolt library: - ```bash - npm install @slack/bolt - ``` + ```bash + npm install @slack/bolt + ``` 3. Create and edit the `app.js` file. Below is an example of the basic structure: - ```js - const { App, LogLevel, ExpressReceiver } = require("@slack/bolt"); - const bodyParser = require("body-parser"); - - const port = process.env.PORT || 6000; - - // Create a Bolt Receiver - const receiver = new ExpressReceiver({ - signingSecret: process.env.SLACK_SIGNING_SECRET, - }); - receiver.router.use(bodyParser.json()); - - // Create the Bolt App, using the receiver - const app = new App({ - token: process.env.SLACK_BOT_TOKEN, - logLevel: LogLevel.DEBUG, - receiver, - }); - - receiver.router.post("/v1/webhook", async (req, res) => { - try { - if (!req.body) { - return res.status(400).send("Error: request body is missing"); - } - - const { title, body } = req.body; - if (!title || !body) { - return res.status(400).send('Error: missing fields: "title", or "body"'); - } - - const payload = req.body.payload; - if (!payload) { - return res.status(400).send('Error: missing "payload" field'); - } - - const { user_email, actions } = payload; - if (!user_email || !actions) { - return res - .status(400) - .send('Error: missing fields: "user_email", "actions"'); - } - - // Get the user ID using Slack API - const userByEmail = await app.client.users.lookupByEmail({ - email: user_email, - }); - - const slackMessage = { - channel: userByEmail.user.id, - text: body, - blocks: [ - { - type: "header", - text: { type: "plain_text", text: title }, - }, - { - type: "section", - text: { type: "mrkdwn", text: body }, - }, - ], - }; - - // Add action buttons if they exist - if (actions && actions.length > 0) { - slackMessage.blocks.push({ - type: "actions", - elements: actions.map((action) => ({ - type: "button", - text: { type: "plain_text", text: action.label }, - url: action.url, - })), - }); - } - - // Post message to the user on Slack - await app.client.chat.postMessage(slackMessage); - - res.status(204).send(); - } catch (error) { - console.error("Error sending message:", error); - res.status(500).send(); - } - }); - - // Acknowledge clicks on link_button, otherwise Slack UI - // complains about missing events. - app.action("button_click", async ({ body, ack, say }) => { - await ack(); // no specific action needed - }); - - // Start the Bolt app - (async () => { - await app.start(port); - console.log("⚡️ Coder Slack bot is running!"); - })(); - ``` + ```js + const { App, LogLevel, ExpressReceiver } = require("@slack/bolt"); + const bodyParser = require("body-parser"); + + const port = process.env.PORT || 6000; + + // Create a Bolt Receiver + const receiver = new ExpressReceiver({ + signingSecret: process.env.SLACK_SIGNING_SECRET, + }); + receiver.router.use(bodyParser.json()); + + // Create the Bolt App, using the receiver + const app = new App({ + token: process.env.SLACK_BOT_TOKEN, + logLevel: LogLevel.DEBUG, + receiver, + }); + + receiver.router.post("/v1/webhook", async (req, res) => { + try { + if (!req.body) { + return res.status(400).send("Error: request body is missing"); + } + + const { title, body } = req.body; + if (!title || !body) { + return res + .status(400) + .send('Error: missing fields: "title", or "body"'); + } + + const payload = req.body.payload; + if (!payload) { + return res.status(400).send('Error: missing "payload" field'); + } + + const { user_email, actions } = payload; + if (!user_email || !actions) { + return res + .status(400) + .send('Error: missing fields: "user_email", "actions"'); + } + + // Get the user ID using Slack API + const userByEmail = await app.client.users.lookupByEmail({ + email: user_email, + }); + + const slackMessage = { + channel: userByEmail.user.id, + text: body, + blocks: [ + { + type: "header", + text: { type: "plain_text", text: title }, + }, + { + type: "section", + text: { type: "mrkdwn", text: body }, + }, + ], + }; + + // Add action buttons if they exist + if (actions && actions.length > 0) { + slackMessage.blocks.push({ + type: "actions", + elements: actions.map((action) => ({ + type: "button", + text: { type: "plain_text", text: action.label }, + url: action.url, + })), + }); + } + + // Post message to the user on Slack + await app.client.chat.postMessage(slackMessage); + + res.status(204).send(); + } catch (error) { + console.error("Error sending message:", error); + res.status(500).send(); + } + }); + + // Acknowledge clicks on link_button, otherwise Slack UI + // complains about missing events. + app.action("button_click", async ({ body, ack, say }) => { + await ack(); // no specific action needed + }); + + // Start the Bolt app + (async () => { + await app.start(port); + console.log("⚡️ Coder Slack bot is running!"); + })(); + ``` 4. Set environment variables to identify the Slack app: - ```bash - export SLACK_BOT_TOKEN=xoxb-... - export SLACK_SIGNING_SECRET=0da4b... - ``` + ```bash + export SLACK_BOT_TOKEN=xoxb-... + export SLACK_SIGNING_SECRET=0da4b... + ``` 5. Start the web application by running: - ```bash - node app.js - ``` + ```bash + node app.js + ``` ## Enable Interactivity in Slack @@ -192,11 +193,8 @@ must respond appropriately. ## Enable Webhook Integration in Coder -To enable webhook integration in Coder, ensure the "notifications" -[experiment is activated](./index.md#enable-experiment) (only required in -v2.15.X). - -Then, define the POST webhook endpoint matching the deployed Slack bot: +To enable webhook integration in Coder, define the POST webhook endpoint +matching the deployed Slack bot: ```bash export CODER_NOTIFICATIONS_WEBHOOK_ENDPOINT=http://localhost:6000/v1/webhook` diff --git a/docs/admin/monitoring/notifications/teams.md b/docs/admin/monitoring/notifications/teams.md index 5846cfc83bc48..0b874a997c54a 100644 --- a/docs/admin/monitoring/notifications/teams.md +++ b/docs/admin/monitoring/notifications/teams.md @@ -15,7 +15,7 @@ Before setting up Microsoft Teams notifications, ensure that you have the following: - Administrator access to the Teams platform -- Coder platform with [notifications enabled](./index.md#enable-experiment) +- Coder platform >=v2.16.0 ## Build Teams Workflow @@ -133,11 +133,8 @@ The process of setting up a Teams workflow consists of three key steps: ## Enable Webhook Integration -To enable webhook integration in Coder, ensure the "notifications" -[experiment is activated](./index.md#enable-experiment) (only required in -v2.15.X). - -Then, define the POST webhook endpoint created by your Teams workflow: +To enable webhook integration in Coder, define the POST webhook endpoint created +by your Teams workflow: ```bash export CODER_NOTIFICATIONS_WEBHOOK_ENDPOINT=https://prod-16.eastus.logic.azure.com:443/workflows/f8fbe3e8211e4b638...`