* Add payload file path to enhance the github action. Increase code coverage. Updated Readme to have the new input type. Added example for the new input type usage. * Add E2E test * Minor OPR changes to align with repo naming conventions. * Minor OPR changes to align with repo naming conventions.
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"text": "Incoming Webhook test for slack send",
|
||||
"blocks": [
|
||||
{
|
||||
"type": "section",
|
||||
"text": {
|
||||
"type": "plain_text",
|
||||
"text": "Content of the event name: {{ github.event_name }}",
|
||||
"emoji": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -80,8 +80,26 @@ jobs:
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_INCOMING_WEBHOOK_URL }}
|
||||
SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
|
||||
|
||||
|
||||
# Use the output from the `slackIncoming` step
|
||||
- name: Check Action output is not empty
|
||||
run: test -n "${{ steps.slackIncoming.outputs.time }}"
|
||||
|
||||
integration_test_file_payload:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: npm ci && npm run build
|
||||
- run: echo "${{ github.event_name }}"
|
||||
- name: Post message to Slack with Payload path
|
||||
id: slackPayloadFile
|
||||
uses: ./
|
||||
with:
|
||||
payload-file-path: ./.github/resources/payload-notification.json
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_INCOMING_WEBHOOK_URL }}
|
||||
SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
|
||||
|
||||
# Use the output from the `slackIncoming` step
|
||||
- name: Check Action output is not empty
|
||||
run: test -n "${{ steps.slackPayloadFile.outputs.time }}"
|
||||
|
||||
@@ -47,6 +47,19 @@ or
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
```
|
||||
or
|
||||
|
||||
> If the `payload` is provided it will take preference over `payload-file-path`
|
||||
|
||||
```
|
||||
- name: Send custom JSON data to Slack workflow
|
||||
id: slack
|
||||
uses: slackapi/[email protected]
|
||||
with:
|
||||
payload-file-path: "./payload-slack-content.json"
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
```
|
||||
|
||||
## Technique 2: Slack App
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
new_push_job:
|
||||
runs-on: ubuntu-latest
|
||||
name: New push to repo
|
||||
steps:
|
||||
- name: Send GitHub trigger payload to Slack Workflow Builder
|
||||
id: slack
|
||||
uses: slackapi/[email protected]
|
||||
with:
|
||||
payload-file-path: "./example-workflows/payloads/example.json"
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"attachments": [
|
||||
{
|
||||
"color": "#d90000",
|
||||
"blocks": [
|
||||
{
|
||||
"type": "section",
|
||||
"text": {
|
||||
"type": "mrkdwn",
|
||||
"text": "${{ github.workflow }} workflow failed on ${{ env.DEFAULT_BRANCH }} branch in the ${{ github.event.repository.name }} repository!"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "divider"
|
||||
},
|
||||
{
|
||||
"type": "actions",
|
||||
"elements": [
|
||||
{
|
||||
"type": "button",
|
||||
"text": {
|
||||
"type": "plain_text",
|
||||
"text": "Build",
|
||||
"emoji": true
|
||||
},
|
||||
"url": "${{ env.REPO_URL }}/actions/runs/${{ github.run_id }}"
|
||||
},
|
||||
{
|
||||
"type": "button",
|
||||
"text": {
|
||||
"type": "plain_text",
|
||||
"text": "Commit",
|
||||
"emoji": true
|
||||
},
|
||||
"url": "${{ env.REPO_URL }}/commit/${{ github.sha }}"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
+24
-4
@@ -2,6 +2,8 @@ const github = require('@actions/github');
|
||||
const { WebClient } = require('@slack/web-api');
|
||||
const flatten = require('flat');
|
||||
const axios = require('axios');
|
||||
const { promises: fs } = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const SLACK_WEBHOOK_TYPES = {
|
||||
WORKFLOW_TRIGGER: 'WORKFLOW_TRIGGER',
|
||||
@@ -26,6 +28,18 @@ module.exports = async function slackSend(core) {
|
||||
|
||||
let payload = core.getInput('payload');
|
||||
|
||||
const payloadFilePath = core.getInput('payload-file-path');
|
||||
|
||||
if (payloadFilePath && !payload) {
|
||||
try {
|
||||
payload = await fs.readFile(path.resolve(payloadFilePath), 'utf-8');
|
||||
} catch (error) {
|
||||
// passed in payload file path was invalid
|
||||
console.error(error);
|
||||
throw new Error(`The payload-file-path may be incorrect. Failed to load the file: ${payloadFilePath}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (payload) {
|
||||
try {
|
||||
// confirm it is valid json
|
||||
@@ -38,15 +52,21 @@ module.exports = async function slackSend(core) {
|
||||
}
|
||||
|
||||
if (typeof botToken !== 'undefined' && botToken.length > 0) {
|
||||
const message = core.getInput('slack-message');
|
||||
const channelId = core.getInput('channel-id');
|
||||
const message = core.getInput('slack-message') || '';
|
||||
const channelId = core.getInput('channel-id') || '';
|
||||
const web = new WebClient(botToken);
|
||||
|
||||
if (channelId.length > 0 && (message.length > 0 || payload)) {
|
||||
if (channelId.length <= 0) {
|
||||
console.log('Channel ID is required to run this action. An empty one has been provided');
|
||||
throw new Error('Channel ID is required to run this action. An empty one has been provided');
|
||||
}
|
||||
|
||||
if (message.length > 0 || payload) {
|
||||
// post message
|
||||
await web.chat.postMessage({ channel: channelId, text: message, ...(payload || {}) });
|
||||
} else {
|
||||
console.log('missing either channel-id, slack-message or payload! Did not send a message via chat.postMessage with botToken');
|
||||
console.log('Missing slack-message or payload! Did not send a message via chat.postMessage with botToken', { channel: channelId, text: message, ...(payload) });
|
||||
throw new Error('Missing message content, please input a valid payload or message to send. No Message has been send.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{not-valid-json
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"oliver": "benji",
|
||||
"bonny": "clyde"
|
||||
}
|
||||
@@ -61,6 +61,24 @@ describe('slack-send', () => {
|
||||
assert.equal(chatArgs.channel, 'C123456', 'Correct channel provided to postMessage');
|
||||
assert.equal(chatArgs.text, 'who let the dogs out?', 'Correct message provided to postMessage');
|
||||
});
|
||||
|
||||
it('should accept a payload-file-path and use it\'s content in the message', async () => {
|
||||
// Prepare
|
||||
fakeCore.getInput.withArgs('channel-id').returns('C123456');
|
||||
fakeCore.getInput.withArgs('payload-file-path').returns('./test/resources/valid-payload.json');
|
||||
|
||||
// Run
|
||||
await slackSend(fakeCore);
|
||||
|
||||
// Assert
|
||||
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.text, '', 'Correct message provided to postMessage');
|
||||
assert.equal(chatArgs.bonny, 'clyde', 'Correct message provided to postMessage');
|
||||
assert.equal(chatArgs.oliver, 'benji', 'Correct message provided to postMessage');
|
||||
});
|
||||
});
|
||||
describe('sad path', () => {
|
||||
it('should set an error if payload cannot be JSON parsed', async () => {
|
||||
@@ -68,6 +86,49 @@ describe('slack-send', () => {
|
||||
await slackSend(fakeCore);
|
||||
assert.include(fakeCore.setFailed.lastCall.firstArg.message, 'Need to provide valid JSON', 'Error set specifying JSON was invalid.');
|
||||
});
|
||||
|
||||
it('should fail if an invalid payload-file-path is provided', async () => {
|
||||
// Prepare
|
||||
fakeCore.getInput.withArgs('channel-id').returns('C123456');
|
||||
fakeCore.getInput.withArgs('payload-file-path').returns('non-existing-path.json');
|
||||
|
||||
// Run
|
||||
await slackSend(fakeCore);
|
||||
|
||||
// Assert
|
||||
assert.include(fakeCore.setFailed.lastCall.firstArg.message, 'The payload-file-path may be incorrect. Failed to load the file: non-existing-path.json', 'Error set specifying JSON was invalid.');
|
||||
});
|
||||
|
||||
it('should fail if a valid payload-file-path with an invalid JSON is provided', async () => {
|
||||
// Prepare
|
||||
fakeCore.getInput.withArgs('channel-id').returns('C123456');
|
||||
fakeCore.getInput.withArgs('payload-file-path').returns('./test/resources/invalid-payload.json');
|
||||
|
||||
// Run
|
||||
await slackSend(fakeCore);
|
||||
|
||||
// Assert
|
||||
assert.include(fakeCore.setFailed.lastCall.firstArg.message, 'Need to provide valid JSON payload', 'Error set specifying JSON was invalid.');
|
||||
});
|
||||
|
||||
it('should fail if Channel ID is missing', async () => {
|
||||
// Run
|
||||
await slackSend(fakeCore);
|
||||
|
||||
// Assert
|
||||
assert.include(fakeCore.setFailed.lastCall.firstArg.message, 'Channel ID is required to run this action. An empty one has been provided', 'Error set specifying JSON was invalid.');
|
||||
});
|
||||
|
||||
it('should fail if payload is missing or empty', async () => {
|
||||
// Prepare
|
||||
fakeCore.getInput.withArgs('channel-id').returns('C123456');
|
||||
|
||||
// Run
|
||||
await slackSend(fakeCore);
|
||||
|
||||
// Assert
|
||||
assert.include(fakeCore.setFailed.lastCall.firstArg.message, 'Missing message content, please input a valid payload or message to send. No Message has been send.', 'Error set specifying JSON was invalid.');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user