Skip to content

Commit

Permalink
feat: Support thread_ts parameter to post the new message as a thread…
Browse files Browse the repository at this point in the history
… reply to another

Closes slackapi#187
  • Loading branch information
ArnaudRinquin committed Apr 22, 2024
1 parent 53b162f commit 067ee68
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 6 deletions.
59 changes: 59 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,65 @@ Please note that **the message update step does not accept a channel name.** Set
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
```

#### Post as a reply to a message

If you would like to log the real-time updates, you can post new messages as thread replies to the message your build job posted in the subsequent steps. In order to do this, the steps after the first message posting can have `thread-ts: ${{ steps.slack.outputs.ts }}` in their settings. With this, the step creates a new message in the thread of the already posted channel message.

Please note that **the reply message step does not accept a channel name.** Set a channel ID for the steps for the actions that update messages.

```yaml
- id: slack
uses: slackapi/[email protected]
with:
# The following message update step does not accept a channel name.
# Setting a channel ID here for consistency is highly recommended.
channel-id: "CHANNEL_ID"
payload: |
{
"text": "Deployment started (In Progress)",
"attachments": [
{
"pretext": "Deployment started",
"color": "dbab09",
"fields": [
{
"title": "Status",
"short": true,
"value": "In Progress"
}
]
}
]
}
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
- uses: slackapi/[email protected]
with:
# Unlike the step posting a new message, this step does not accept a channel name.
# Please use a channel ID, not a name here.
channel-id: "CHANNEL_ID"
thread-ts: ${{ steps.slack.outputs.ts }}
payload: |
{
"text": "Deployment finished (Completed)",
"attachments": [
{
"pretext": "Deployment finished",
"color": "28a745",
"fields": [
{
"title": "Status",
"short": true,
"value": "Completed"
}
]
}
]
}
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
```

### Technique 3: Slack Incoming Webhook

This approach allows your GitHub Actions job to post a message to a Slack channel or direct message by utilizing [Incoming Webhooks](https://api.slack.com/messaging/webhooks).
Expand Down
3 changes: 3 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ inputs:
update-ts: # The timestamp of a previous message posted to update it instead of posting a new message
description: 'The timestamp of a previous message posted. It will update the existing message instead of posting a new message'
required: false
thread-ts: # The timestamp of a previous message posted to post a new message as a thread reply to the existing message
description: 'The timestamp of a previous message posted. It will post the new message as a thread reply to the existing message'
required: false
outputs:
time: # id of output
description: 'The time'
Expand Down
23 changes: 17 additions & 6 deletions src/slack-send.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,25 @@ module.exports = async function slackSend(core) {
}

if (message.length > 0 || payload) {
const ts = core.getInput('update-ts');
const updateTs = core.getInput('update-ts');
const threadTs = core.getInput('thread-ts');
await Promise.all(channelIds.split(',').map(async (channelId) => {
if (ts) {
// update message
webResponse = await web.chat.update({ ts, channel: channelId.trim(), text: message, ...(payload || {}) });
if (updateTs) {
// update message
webResponse = await web.chat.update({
ts: updateTs,
channel: channelId.trim(),
text: message,
...(payload || {}),
});
} else {
// post message
webResponse = await web.chat.postMessage({ channel: channelId.trim(), text: message, ...(payload || {}) });
// post message
webResponse = await web.chat.postMessage({
thread_ts: threadTs,
channel: channelId.trim(),
text: message,
...(payload || {}),
});
}
}));
} else {
Expand Down
16 changes: 16 additions & 0 deletions test/slack-send-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,22 @@ describe('slack-send', () => {
assert.equal(chatArgs.text, 'who let the dogs out?', 'Correct message provided to postMessage');
});

it('should send a reply-message using the postMessage API', async () => {
fakeCore.getInput.withArgs('slack-message').returns('who let the dogs out?');
fakeCore.getInput.withArgs('channel-id').returns('C123456');
fakeCore.getInput.withArgs('thread-ts').returns('123123');
await slackSend(fakeCore);
assert.equal(fakeCore.setOutput.firstCall.firstArg, 'ts', 'Output name set to ts');
assert.equal(fakeCore.setOutput.secondCall.firstArg, 'thread_ts', 'Output name set to thread_ts');
assert(fakeCore.setOutput.secondCall.lastArg.length > 0, 'Time output a non-zero-length string');
assert.equal(fakeCore.setOutput.lastCall.firstArg, 'time', 'Output name set to time');
assert(fakeCore.setOutput.lastCall.lastArg.length > 0, 'Time output a non-zero-length string');
const chatArgs = ChatStub.postMessage.lastCall.firstArg;
assert.equal(chatArgs.channel, 'C123456', 'Correct channel provided to postMessage');
assert.equal(chatArgs.thread_ts, '123123', 'Correct thread_ts provided to postMessage');
assert.equal(chatArgs.text, 'who let the dogs out?', 'Correct message provided to postMessage');
});

it('should send a message using the update API', async () => {
fakeCore.getInput.withArgs('slack-message').returns('who let the dogs out?');
fakeCore.getInput.withArgs('channel-id').returns('C123456');
Expand Down

0 comments on commit 067ee68

Please sign in to comment.