Skip to content

Commit d6a4a69

Browse files
committed
fetching inputs and improved tests
1 parent c5d47e3 commit d6a4a69

File tree

7 files changed

+217
-2
lines changed

7 files changed

+217
-2
lines changed

__tests__/functions/deployment-confirmation.test.js

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,57 @@ test('successfully prompts for deployment confirmation and gets confirmed by the
139139
})
140140
})
141141

142+
test('successfully prompts for deployment confirmation and gets confirmed by the original actor with some null data params in the issue comment', async () => {
143+
data.params = null
144+
data.parsed_params = null
145+
data.environmentUrl = null
146+
147+
// Mock that the user adds a +1 reaction
148+
octokit.rest.reactions.listForIssueComment.mockResolvedValueOnce({
149+
data: [
150+
{
151+
user: {login: 'monalisa'},
152+
content: '+1'
153+
}
154+
]
155+
})
156+
157+
const result = await deploymentConfirmation(context, octokit, data)
158+
159+
expect(result).toBe(true)
160+
expect(octokit.rest.issues.createComment).toHaveBeenCalledWith({
161+
body: expect.stringContaining('"url": null'),
162+
issue_number: 1,
163+
owner: 'corp',
164+
repo: 'test',
165+
headers: API_HEADERS
166+
})
167+
expect(core.debug).toHaveBeenCalledWith(
168+
'deployment confirmation comment id: 124'
169+
)
170+
expect(core.info).toHaveBeenCalledWith(
171+
`🕒 waiting ${COLORS.highlight}60${COLORS.reset} seconds for deployment confirmation`
172+
)
173+
expect(core.info).toHaveBeenCalledWith(
174+
`✅ deployment confirmed by ${COLORS.highlight}monalisa${COLORS.reset} - sha: ${COLORS.highlight}abc123${COLORS.reset}`
175+
)
176+
177+
expect(octokit.rest.reactions.listForIssueComment).toHaveBeenCalledWith({
178+
comment_id: 124,
179+
owner: 'corp',
180+
repo: 'test',
181+
headers: API_HEADERS
182+
})
183+
184+
expect(octokit.rest.issues.updateComment).toHaveBeenCalledWith({
185+
body: expect.stringContaining('✅ Deployment confirmed by __monalisa__'),
186+
comment_id: 124,
187+
owner: 'corp',
188+
repo: 'test',
189+
headers: API_HEADERS
190+
})
191+
})
192+
142193
test('user rejects the deployment with thumbs down', async () => {
143194
// Mock that the user adds a -1 reaction
144195
octokit.rest.reactions.listForIssueComment.mockResolvedValueOnce({
@@ -242,6 +293,67 @@ test('ignores reactions from other users', async () => {
242293
)
243294
})
244295

296+
test('ignores non thumbsUp/thumbsDown reactions from the original actor', async () => {
297+
// Mock reactions list with various reaction types from original actor
298+
octokit.rest.reactions.listForIssueComment.mockResolvedValueOnce({
299+
data: [
300+
{
301+
user: {login: 'monalisa'},
302+
content: 'confused'
303+
},
304+
{
305+
user: {login: 'monalisa'},
306+
content: 'eyes'
307+
},
308+
{
309+
user: {login: 'monalisa'},
310+
content: 'rocket'
311+
}
312+
]
313+
})
314+
315+
// Add a thumbs up in the second poll
316+
octokit.rest.reactions.listForIssueComment.mockResolvedValueOnce({
317+
data: [
318+
{
319+
user: {login: 'monalisa'},
320+
content: 'confused'
321+
},
322+
{
323+
user: {login: 'monalisa'},
324+
content: 'eyes'
325+
},
326+
{
327+
user: {login: 'monalisa'},
328+
content: 'rocket'
329+
},
330+
{
331+
user: {login: 'monalisa'},
332+
content: '+1'
333+
}
334+
]
335+
})
336+
337+
const result = await deploymentConfirmation(context, octokit, data)
338+
339+
expect(result).toBe(true)
340+
expect(octokit.rest.reactions.listForIssueComment).toHaveBeenCalledTimes(2)
341+
342+
// Verify that debug was called for each ignored reaction type
343+
expect(core.debug).toHaveBeenCalledWith('ignoring reaction: confused')
344+
expect(core.debug).toHaveBeenCalledWith('ignoring reaction: eyes')
345+
expect(core.debug).toHaveBeenCalledWith('ignoring reaction: rocket')
346+
347+
// Verify final confirmation happened
348+
expect(octokit.rest.issues.updateComment).toHaveBeenCalledWith({
349+
body: expect.stringContaining('✅ Deployment confirmed by __monalisa__'),
350+
comment_id: 124,
351+
owner: 'corp',
352+
repo: 'test',
353+
headers: API_HEADERS
354+
})
355+
})
356+
245357
test('handles API errors gracefully', async () => {
246358
// First call throws error
247359
octokit.rest.reactions.listForIssueComment.mockRejectedValueOnce(

__tests__/main.test.js

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import * as nakedCommandCheck from '../src/functions/naked-command-check'
1717
import * as validDeploymentOrder from '../src/functions/valid-deployment-order'
1818
import * as commitSafetyChecks from '../src/functions/commit-safety-checks'
1919
import * as timestamp from '../src/functions/timestamp'
20+
import * as deploymentConfirmation from '../src/functions/deployment-confirmation'
2021
import {COLORS} from '../src/functions/colors'
2122

2223
const setOutputMock = jest.spyOn(core, 'setOutput')
@@ -91,6 +92,8 @@ beforeEach(() => {
9192
process.env.INPUT_IGNORED_CHECKS = ''
9293
process.env.INPUT_USE_SECURITY_WARNINGS = 'true'
9394
process.env.INPUT_ALLOW_NON_DEFAULT_TARGET_BRANCH_DEPLOYMENTS = 'false'
95+
process.env.INPUT_DEPLOYMENT_CONFIRMATION = 'false'
96+
process.env.INPUT_DEPLOYMENT_CONFIRMATION_TIMEOUT = '60'
9497

9598
github.context.payload = {
9699
issue: {
@@ -148,6 +151,11 @@ beforeEach(() => {
148151
jest.spyOn(isDeprecated, 'isDeprecated').mockImplementation(() => {
149152
return false
150153
})
154+
jest
155+
.spyOn(deploymentConfirmation, 'deploymentConfirmation')
156+
.mockImplementation(() => {
157+
return true
158+
})
151159
jest.spyOn(lock, 'lock').mockImplementation(() => {
152160
return true
153161
})
@@ -220,6 +228,81 @@ test('successfully runs the action', async () => {
220228
)
221229
})
222230

231+
test('successfully runs the action with deployment confirmation', async () => {
232+
process.env.INPUT_DEPLOYMENT_CONFIRMATION = 'true'
233+
234+
jest
235+
.spyOn(deploymentConfirmation, 'deploymentConfirmation')
236+
.mockImplementation(() => {
237+
return true
238+
})
239+
240+
expect(await run()).toBe('success')
241+
expect(setOutputMock).toHaveBeenCalledWith('deployment_id', 123)
242+
expect(setOutputMock).toHaveBeenCalledWith('comment_body', '.deploy')
243+
expect(setOutputMock).toHaveBeenCalledWith('triggered', 'true')
244+
expect(setOutputMock).toHaveBeenCalledWith('comment_id', 123)
245+
expect(setOutputMock).toHaveBeenCalledWith('ref', 'test-ref')
246+
expect(setOutputMock).toHaveBeenCalledWith('noop', false)
247+
expect(setOutputMock).toHaveBeenCalledWith('continue', 'true')
248+
expect(saveStateMock).toHaveBeenCalledWith('isPost', 'true')
249+
expect(saveStateMock).toHaveBeenCalledWith('actionsToken', 'faketoken')
250+
expect(saveStateMock).toHaveBeenCalledWith('environment', 'production')
251+
expect(saveStateMock).toHaveBeenCalledWith('comment_id', 123)
252+
expect(saveStateMock).toHaveBeenCalledWith('ref', 'test-ref')
253+
expect(saveStateMock).toHaveBeenCalledWith('noop', false)
254+
expect(setOutputMock).toHaveBeenCalledWith('type', 'deploy')
255+
expect(saveStateMock).toHaveBeenCalledWith('deployment_id', 123)
256+
expect(saveStateMock).toHaveBeenCalledWith('sha', 'abc123')
257+
expect(debugMock).toHaveBeenCalledWith('production_environment: true')
258+
expect(debugMock).toHaveBeenCalledWith(
259+
'deploymentConfirmation() was successful - continuing with the deployment'
260+
)
261+
expect(saveStateMock).not.toHaveBeenCalledWith('environment_url', String)
262+
expect(setOutputMock).not.toHaveBeenCalledWith('environment_url', String)
263+
expect(infoMock).toHaveBeenCalledWith(
264+
`🧑‍🚀 commit sha to deploy: ${COLORS.highlight}${mock_sha}${COLORS.reset}`
265+
)
266+
expect(infoMock).toHaveBeenCalledWith(
267+
`🚀 ${COLORS.success}deployment started!${COLORS.reset}`
268+
)
269+
})
270+
271+
test('rejects the deployment when deployment confirmation is set, but does not succeed', async () => {
272+
process.env.INPUT_DEPLOYMENT_CONFIRMATION = 'true'
273+
274+
jest
275+
.spyOn(deploymentConfirmation, 'deploymentConfirmation')
276+
.mockImplementation(() => {
277+
return false
278+
})
279+
280+
expect(await run()).toBe('failure')
281+
expect(setOutputMock).toHaveBeenCalledWith('comment_body', '.deploy')
282+
expect(setOutputMock).toHaveBeenCalledWith('triggered', 'true')
283+
expect(setOutputMock).toHaveBeenCalledWith('comment_id', 123)
284+
expect(setOutputMock).toHaveBeenCalledWith('ref', 'test-ref')
285+
expect(setOutputMock).not.toHaveBeenCalledWith('continue', 'true')
286+
expect(saveStateMock).toHaveBeenCalledWith('isPost', 'true')
287+
expect(saveStateMock).toHaveBeenCalledWith('actionsToken', 'faketoken')
288+
expect(saveStateMock).toHaveBeenCalledWith('environment', 'production')
289+
expect(saveStateMock).toHaveBeenCalledWith('comment_id', 123)
290+
expect(saveStateMock).toHaveBeenCalledWith('ref', 'test-ref')
291+
expect(saveStateMock).not.toHaveBeenCalledWith('noop', false)
292+
expect(setOutputMock).toHaveBeenCalledWith('type', 'deploy')
293+
expect(saveStateMock).toHaveBeenCalledWith('sha', 'abc123')
294+
expect(debugMock).not.toHaveBeenCalledWith('production_environment: true')
295+
expect(debugMock).toHaveBeenCalledWith(
296+
'❌ deployment not confirmed - exiting'
297+
)
298+
expect(saveStateMock).not.toHaveBeenCalledWith('environment_url', String)
299+
expect(setOutputMock).not.toHaveBeenCalledWith('environment_url', String)
300+
expect(saveStateMock).toHaveBeenCalledWith('bypass', 'true')
301+
expect(infoMock).not.toHaveBeenCalledWith(
302+
`🧑‍🚀 commit sha to deploy: ${COLORS.highlight}${mock_sha}${COLORS.reset}`
303+
)
304+
})
305+
223306
test('successfully runs the action on a deployment to development and with branch updates disabled', async () => {
224307
process.env.INPUT_UPDATE_BRANCH = 'disabled'
225308
github.context.payload.comment.body = '.deploy to development'

badges/coverage.svg

Lines changed: 1 addition & 1 deletion
Loading

dist/index.js

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/functions/deployment-confirmation.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ export async function deploymentConfirmation(context, octokit, data) {
125125
)
126126

127127
return false
128+
} else {
129+
core.debug(`ignoring reaction: ${reaction.content}`)
128130
}
129131
} else {
130132
core.debug(

src/functions/inputs.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ export function getInputs() {
5959
const allow_non_default_target_branch_deployments = core.getBooleanInput(
6060
'allow_non_default_target_branch_deployments'
6161
)
62+
const deployment_confirmation = core.getBooleanInput(
63+
'deployment_confirmation'
64+
)
65+
const deployment_confirmation_timeout = core.getInput(
66+
'deployment_confirmation_timeout'
67+
)
6268

6369
// validate inputs
6470
validateInput('update_branch', update_branch, ['disabled', 'warn', 'force'])
@@ -109,6 +115,8 @@ export function getInputs() {
109115
enforced_deployment_order: enforced_deployment_order,
110116
commit_verification: commit_verification,
111117
ignored_checks: ignored_checks,
118+
deployment_confirmation: deployment_confirmation,
119+
deployment_confirmation_timeout: deployment_confirmation_timeout,
112120
use_security_warnings: use_security_warnings,
113121
allow_non_default_target_branch_deployments:
114122
allow_non_default_target_branch_deployments

0 commit comments

Comments
 (0)