diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 7e8c43e..e43fccf 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -69,4 +69,4 @@ jobs: # sam build - run: sam build --use-container # sam deploy - - run: sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --parameter-overrides SlackTokenSecret=${{ secrets.SLACKTOKEN }} SmallImprovementsTokenSecret=${{ secrets.SITOKEN }} SlackChannel=goals ScheduleEnabled=true + - run: sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --parameter-overrides SlackTokenSecret=${{ secrets.SLACKTOKEN }} SmallImprovementsTokenSecret=${{ secrets.SITOKEN }} SlackChannel=CF4U95FN0 ScheduleEnabled=true diff --git a/it/integration.test.js b/it/integration.test.js index 1810626..a6b62e6 100644 --- a/it/integration.test.js +++ b/it/integration.test.js @@ -2,7 +2,7 @@ const index = require('../src/index'); describe('integration', () => { const event = { - time: '2022-06-16T00:00:00Z' + time: '2025-10-30T00:00:00Z' }; test('process event', async () => { diff --git a/src/index.js b/src/index.js index 579d0ca..1767752 100644 --- a/src/index.js +++ b/src/index.js @@ -58,11 +58,13 @@ async function main(event, context) { }) ); const allPostResults = completedResults.concat(createdResults); - const successfulPosts = allPostResults.filter(x => x.value); const failedPosts = allPostResults.filter(x => x.status === 'rejected'); + const nonErrorPosts = allPostResults.filter(x => x.status === 'fulfilled'); + const successfulPosts = nonErrorPosts.filter(x => x.value !== undefined); + const skippedPosts = nonErrorPosts.filter(x => x.value === undefined); failedPosts.forEach(fail => console.log(fail.reason)); - const message = `Finished ${successfulPosts.length} successfully. Failed ${failedPosts.length}`; + const message = `Finished ${successfulPosts.length} successfully. Failed ${failedPosts.length}. ${skippedPosts.length} already existed (skipped)`; console.log(message); return message; } diff --git a/src/slack-service.js b/src/slack-service.js index af021c1..00d382b 100644 --- a/src/slack-service.js +++ b/src/slack-service.js @@ -1,15 +1,15 @@ const slackClient = require('./slack'); // Get Slack ID, Format Message, Post -async function PostCompletedObjective(token, channelName, content, newStatus, email) { +async function PostCompletedObjective(token, channelId, content, newStatus, email) { const slackID = await slackClient.getSlackID(email, token); const formattedMessage = await slackClient.formatSlackMessageForCompleted(content.objective, newStatus, slackID, content.cycle.id); - return await slackClient.slackPost(token, channelName, formattedMessage); + return await slackClient.slackPost(token, channelId, formattedMessage); } -async function PostCreatedObjective(token, channelName, content, email) { +async function PostCreatedObjective(token, channelId, content, email) { const slackID = await slackClient.getSlackID(email, token); const formattedMessage = await slackClient.formatSlackMessageForCreated(content.objective, slackID, content.cycle.id); - return await slackClient.slackPost(token, channelName, formattedMessage); + return await slackClient.slackPost(token, channelId, formattedMessage); } exports.PostCompletedObjective = PostCompletedObjective; diff --git a/src/slack.js b/src/slack.js index d860de0..172f395 100644 --- a/src/slack.js +++ b/src/slack.js @@ -4,8 +4,8 @@ const messageVariables = { }; // Post a message to a channel your app is in using ID and message text -async function slackPost(authToken, channelName, formattedMessage) { // postData should be JSON, e.g. { channel:"#channel", text:'message' } - formattedMessage.channel = '' + channelName; +async function slackPost(authToken, channelId, formattedMessage) { // postData should be JSON, e.g. { channel:"#channel", text:'message' } + formattedMessage.channel = '' + channelId; const options = { hostname: 'sourceallies.slack.com', @@ -30,7 +30,12 @@ async function slackPost(authToken, channelName, formattedMessage) { // postData }); res.on('end', () => { const responseBody = Buffer.concat(body).toString(); - resolve(responseBody); + const jsonResponse = JSON.parse(responseBody); + if (jsonResponse.ok === true) { + resolve(responseBody); + } else { + reject(new Error(`Slack post failed with error: ${jsonResponse.error}`)); + } }); }); req.on('error', (e) => { @@ -118,8 +123,13 @@ function getSlackID(email, token) { res.on('data', d => { responsePayload += d; }); - res.on('close', () => { - resolve(JSON.parse(responsePayload).user.id); + res.on('end', () => { + const responseObject = JSON.parse(responsePayload); + if (typeof responseObject.user === 'undefined' || responseObject.user.id === 'undefined') { + reject(new Error(`Unexpected slack ID response: ${responsePayload}`)); + } else { + resolve(responseObject.user.id); + } }); }); req.on('error', err => { diff --git a/src/small-improvements.js b/src/small-improvements.js index 67cb145..80be0a3 100644 --- a/src/small-improvements.js +++ b/src/small-improvements.js @@ -24,7 +24,7 @@ function getObjectives(token) { res.on('data', d => { responsePayload += d; }); - res.on('close', () => { + res.on('end', () => { resolve(JSON.parse(responsePayload)); }); }); @@ -54,12 +54,11 @@ function getEmail(SIUID, token) { // SIUID (Small Improvements User ID) is in th if (res.statusCode !== 200) { console.log(`status logged ${res.statusCode}`); reject(new Error(`Could not get email: ${res.statusCode}`)); - return; } res.on('data', d => { responsePayload += d; }); - res.on('close', () => { + res.on('end', () => { resolve(JSON.parse(responsePayload).loginname); }); }); diff --git a/test/index.test.js b/test/index.test.js index 725ae33..e6daa1c 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -81,14 +81,14 @@ describe('index', () => { }]; }); - test('should not post previously existing objective', async () => { + test('should not post previously existing objectives', async () => { secretsClient.getSecret.mockResolvedValue(secrets); smallImprovementsClient.GetObjectives.mockResolvedValue(activities); dynamodbClient.getRecord.mockResolvedValue(dynamoRecords); const result = await index.handler(event); - expect(result).toBe('Finished 0 successfully. Failed 0'); + expect(result).toBe('Finished 0 successfully. Failed 0. 2 already existed (skipped)'); expect(dynamodbClient.getRecord).toHaveBeenCalledWith(objectiveId); expect(dynamodbClient.insertRecord).not.toHaveBeenCalled(); }); @@ -105,7 +105,7 @@ describe('index', () => { const result = await index.handler(event); - expect(result).toBe('Finished 2 successfully. Failed 0'); + expect(result).toBe('Finished 2 successfully. Failed 0. 0 already existed (skipped)'); expect(dynamodbClient.getRecord).toHaveBeenCalledWith(objectiveId); expect(dynamodbClient.getRecord).toHaveBeenCalledWith(objectiveId + 'CREATED'); expect(dynamodbClient.insertRecord).toHaveBeenCalledWith(activities.items[0].items[0].activities[0], ''); @@ -139,7 +139,7 @@ describe('index', () => { const result = await index.handler(event); - expect(result).toBe('Finished 2 successfully. Failed 1'); + expect(result).toBe('Finished 2 successfully. Failed 1. 0 already existed (skipped)'); expect(dynamodbClient.getRecord).toHaveBeenCalledWith(objectiveId); expect(dynamodbClient.getRecord).toHaveBeenCalledWith(secondObjectiveId); expect(dynamodbClient.getRecord).toHaveBeenCalledWith(objectiveId + 'CREATED'); diff --git a/test/slack.test.js b/test/slack.test.js index c4bcbd0..1a15509 100644 --- a/test/slack.test.js +++ b/test/slack.test.js @@ -24,24 +24,24 @@ describe('Slack Requests', () => { mockSlackID = 'Reece'; mockCycleId = 'CycleId'; responseBody = `{ - ok: true, - channel: 'C0179PL5K8E', - ts: '1595354927.001300', - message: { - bot_id: 'B017GED1UEN', - type: 'message', - text: 'Hello, World!', - user: 'U0171MZ51E3', - ts: '1595354927.001300', - team: 'T2CA1AURM', - bot_profile: { - id: 'B017GED1UEN', - deleted: false, - name: 'My Test App', - updated: 1595353545, - app_id: 'A017NKGAKHA', - icons: [Object], - team_id: 'T2CA1AURM' + "ok": true, + "channel": "C0179PL5K8E", + "ts": "1595354927.001300", + "message": { + "bot_id": "B017GED1UEN", + "type": "message", + "text": "Hello, World!", + "user": "U0171MZ51E3", + "ts": "1595354927.001300", + "team": "T2CA1AURM", + "bot_profile": { + "id": "B017GED1UEN", + "deleted": false, + "name": "My Test App", + "updated": 1595353545, + "app_id": "A017NKGAKHA", + "icons": [], + "team_id": "T2CA1AURM" } } }`;