[#43] Add payload file path to enhance the github action. (#44)

* 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:
Umbert
2022-01-10 14:59:55 -08:00
committed by GitHub
parent fab315ed30
commit 94aef8cf88
9 changed files with 191 additions and 5 deletions
@@ -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
}
}
]
}
+19 -1
View File
@@ -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 }}"
+13
View File
@@ -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 }}
+42
View File
@@ -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
View File
@@ -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.');
}
}
+1
View File
@@ -0,0 +1 @@
{not-valid-json
+4
View File
@@ -0,0 +1,4 @@
{
"oliver": "benji",
"bonny": "clyde"
}
+61
View File
@@ -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.');
});
});
});