- Actions
- Post Message
Actions
Post Message
Post a message to a Slack channel
Publish Slack messages to a public or private channel in your Slack Workspace as the Trigger.dev Slack bot. If you need to publish messages to your customer’s Slack channels, consider using Incoming Webhooks and our fetch function.
Params
A unique string. Please see the Keys and Resumability doc for more info.
The name of the channel, can optionally include the #
. E.g. #team
.
Alternatively you can use the channelId
param.
The slack ID of the channel, e.g. C04GWUTDC4W
. Can be used instead of channelName
. Use channelId
if the slack channel name could change.
The formatted text of the message to be published, formatted as mrkdwn.
You can use blocks to create a rich message with images, buttons, and more.
You can either pass in a JavaScript object or use JSX Slack to create blocks. We highly recommend using JSX Slack as it’s much easier to read and write. See the block example to see it in action.
For full details on Slack blocks, see the Slack API docs.
The “timestamp ID” of the message to reply to. If not specified, the message will be published as a new thread.
A JSON object that will be attached to the message. This can be used to store custom data about the message, but will not be displayed to users. Useful for passing data to a blockActionInteraction trigger.
The name of the bot that will publish the message. If not specified, the message will be published as the Trigger.dev Slack bot.
The emoji to use as the icon for the bot that will publish the message. If not specified, the message will be published as the Trigger.dev Slack bot.
The URL of an image to use as the icon for the bot that will publish the message. If not specified, the message will be published as the Trigger.dev Slack bot.
Response
Always true; non-ok responses will halt the workflow run and throw an error.
The channel ID of the channel the message was published to.
The “timestamp ID” of the message, which can be used to update or delete the message.
Example Workflows
Notify Slack on New GitHub Star
import * as github from "@trigger.dev/github";
import * as slack from "@trigger.dev/slack";
new Trigger({
id: "new-star",
name: "On New Star",
on: github.events.newStarEvent({
repo: "triggerdotdev/trigger.dev",
}),
run: async (event, ctx) => {
await slack.postMessage("⭐️ New Star", {
channelName: "github-stars",
text: `Repo ${event.repository.full_name} got a star from ${event.sender.login}, for a total of ${event.repository.stargazers_count} stars!`,
});
},
}).listen();
Blocks with interactivity
You can add interaction and richer visual elements using Blocks. The easiest way to add them is using jsx-slack
(which is a separate npm package that you can install).
This example messages your team every minute (!) and asks them how they’re doing. There are two buttons and a dropdown menu.
In this examples there are two workflows:
- Messages your team every minute (!) and asks them how they’re doing.
- Receives the interaction from users. It adds reactions when the buttons are pressed and posts a message when a user selects from the dropdown menu.
Please note, that to use jsx-slack
you will need to add the jsxImportSource
pragma to the top of your file. This is because jsx-slack
is not a React library, but it uses the same syntax as React. Also, you might need to add "jsx": "react-jsx"
to your compilerOption
in tsconfig.json
. The workflow file needs to be a .jsx
or .tsx
file (like when you use React).
/** @jsxImportSource jsx-slack */
import * as slack from "@trigger.dev/slack";
import JSXSlack, {
Actions,
Blocks,
Button,
Section,
Select,
Option,
} from "jsx-slack";
import { z } from "zod";
const BLOCK_ID = "issue.action.block";
//1. every minute see how your employees are doing, we don't recommend this frequency 😉
new Trigger({
id: "slack-interactivity",
name: "Testing Slack Interactivity",
on: scheduleEvent({
rateOf: {
minutes: 1,
},
}),
run: async (event, ctx) => {
await slack.postMessage("jsx-test", {
channelName: "test-integrations",
//text appears in Slack notifications on mobile/desktop
text: "How is your progress today?",
//import and use JSXSlack to make creating rich messages much easier
blocks: JSXSlack(
<Blocks>
<Section>How is your progress today?</Section>
<Actions blockId={BLOCK_ID}>
<Button value="blocked" actionId="status-blocked">
I'm blocked
</Button>
<Button
value="help"
actionId="status-help"
url="https://xkcd.com/1349/"
>
Get help
</Button>
<Select actionId="rating" placeholder="Rate it!">
<Option value="5">5 {":star:".repeat(5)}</Option>
<Option value="4">4 {":star:".repeat(4)}</Option>
<Option value="3">3 {":star:".repeat(3)}</Option>
<Option value="2">2 {":star:".repeat(2)}</Option>
<Option value="1">1 {":star:".repeat(1)}</Option>
</Select>
</Actions>
</Blocks>
),
});
},
}).listen();
//2. this workflow listens for Slack interactions filtered by the block id and actions we used above
new Trigger({
id: "slack-block-interaction",
name: "Slack Block Interaction",
on: slack.events.blockActionInteraction({
blockId: BLOCK_ID,
actionId: ["status-blocked", "status-help", "rating"],
}),
run: async (event, ctx) => {
//create promises from all the actions
const promises = event.actions.map((action) => {
switch (action.action_id) {
case "status-blocked": {
//the user is blocked so add a 😢 emoji as a reaction
if (event.message) {
return slack.addReaction("React to message", {
name: "cry",
timestamp: event.message.ts,
channelId: event.channel.id,
});
}
break;
}
case "status-help": {
//the user needs help so add an 🆘 emoji as a reaction
if (event.message) {
return slack.addReaction("React to message", {
name: "sos",
timestamp: event.message.ts,
channelId: event.channel.id,
});
}
break;
}
case "rating": {
if (action.type != "static_select") {
throw new Error("This action should be a select");
}
//post the rating as a message that appears below the original,
//only the user pressing the button will see this message
return slack.postMessageResponse(
"Added a comment to the issue",
event.response_url,
{
text: `You rated your day ${action.selected_option?.value} stars`,
replace_original: false,
}
);
}
default:
return Promise.resolve();
}
});
await Promise.all(promises);
},
}).listen();