diff --git a/__tests__/functions/deployment-confirmation.test.js b/__tests__/functions/deployment-confirmation.test.js
index ff32b40f..deaeec5a 100644
--- a/__tests__/functions/deployment-confirmation.test.js
+++ b/__tests__/functions/deployment-confirmation.test.js
@@ -75,6 +75,7 @@ beforeEach(() => {
data = {
deployment_confirmation_timeout: 60,
deploymentType: 'branch',
+ deploymentApiType: 'deploy',
environment: 'production',
environmentUrl: 'https://example.com',
log_url: 'https://github.com/corp/test/actions/runs/12345',
@@ -141,6 +142,56 @@ test('successfully prompts for deployment confirmation and gets confirmed by the
})
})
+test('successfully prompts for destroy confirmation and gets confirmed by the original actor', async () => {
+ // Mock that the user adds a +1 reaction
+ octokit.rest.reactions.listForIssueComment.mockResolvedValueOnce({
+ data: [
+ {
+ user: {login: 'monalisa'},
+ content: '+1'
+ }
+ ]
+ })
+
+ data.deploymentType = 'destroy'
+ data.deploymentApiType = 'destroy'
+
+ const result = await deploymentConfirmation(context, octokit, data)
+
+ expect(result).toBe(true)
+ expect(octokit.rest.issues.createComment).toHaveBeenCalledWith({
+ body: expect.stringContaining('Deployment Type: `destroy`'),
+ issue_number: 1,
+ owner: 'corp',
+ repo: 'test',
+ headers: API_HEADERS
+ })
+ expect(core.debug).toHaveBeenCalledWith(
+ 'deployment confirmation comment id: 124'
+ )
+ expect(core.info).toHaveBeenCalledWith(
+ `🕒 waiting ${COLORS.highlight}60${COLORS.reset} seconds for deployment confirmation`
+ )
+ expect(core.info).toHaveBeenCalledWith(
+ `✅ deployment confirmed by ${COLORS.highlight}monalisa${COLORS.reset} - sha: ${COLORS.highlight}abc123${COLORS.reset}`
+ )
+
+ expect(octokit.rest.reactions.listForIssueComment).toHaveBeenCalledWith({
+ comment_id: 124,
+ owner: 'corp',
+ repo: 'test',
+ headers: API_HEADERS
+ })
+
+ expect(octokit.rest.issues.updateComment).toHaveBeenCalledWith({
+ body: expect.stringContaining('✅ Deployment confirmed by __monalisa__'),
+ comment_id: 124,
+ owner: 'corp',
+ repo: 'test',
+ headers: API_HEADERS
+ })
+})
+
test('successfully prompts for deployment confirmation and gets confirmed by the original actor with some null data params in the issue comment', async () => {
data.params = null
data.parsed_params = null
diff --git a/__tests__/functions/environment-targets.test.js b/__tests__/functions/environment-targets.test.js
index ca4748cf..c600ec51 100644
--- a/__tests__/functions/environment-targets.test.js
+++ b/__tests__/functions/environment-targets.test.js
@@ -24,6 +24,7 @@ const environment = 'production'
const body = '.deploy'
const trigger = '.deploy'
const noop_trigger = '.noop'
+const destroy_trigger = '.destroy'
const stable_branch = 'main'
const environmentUrls =
'production|https://example.com,development|https://dev.example.com,staging|http://staging.example.com'
@@ -35,6 +36,7 @@ test('checks the comment body and does not find an explicit environment target',
body,
trigger,
noop_trigger,
+ destroy_trigger,
stable_branch
)
).toStrictEqual({
@@ -43,6 +45,7 @@ test('checks the comment body and does not find an explicit environment target',
environmentObj: {
target: 'production',
noop: false,
+ destroy: false,
stable_branch_used: false,
params: null,
parsed_params: null,
@@ -61,6 +64,7 @@ test('checks the comment body and finds an explicit environment target for devel
'.deploy development',
trigger,
noop_trigger,
+ destroy_trigger,
stable_branch
)
).toStrictEqual({
@@ -69,6 +73,7 @@ test('checks the comment body and finds an explicit environment target for devel
environmentObj: {
target: 'development',
noop: false,
+ destroy: false,
stable_branch_used: false,
params: null,
parsed_params: null,
@@ -87,6 +92,7 @@ test('checks the comment body and finds an explicit environment target for devel
'.deploy development | something1 something2 something3',
trigger,
noop_trigger,
+ destroy_trigger,
stable_branch
)
).toStrictEqual({
@@ -95,6 +101,7 @@ test('checks the comment body and finds an explicit environment target for devel
environmentObj: {
target: 'development',
noop: false,
+ destroy: false,
stable_branch_used: false,
params: 'something1 something2 something3',
parsed_params: {_: ['something1', 'something2', 'something3']},
@@ -120,6 +127,7 @@ test('checks the comment body and finds an explicit environment target and an ex
'.deploy 82c238c277ca3df56fe9418a5913d9188eafe3bc development | something1 something2 something3',
trigger,
noop_trigger,
+ destroy_trigger,
stable_branch
)
).toStrictEqual({
@@ -128,6 +136,7 @@ test('checks the comment body and finds an explicit environment target and an ex
environmentObj: {
target: 'development',
noop: false,
+ destroy: false,
stable_branch_used: false,
params: 'something1 something2 something3',
parsed_params: {_: ['something1', 'something2', 'something3']},
@@ -153,6 +162,7 @@ test('checks the comment body and finds an explicit environment target and an ex
'.noop 82c238c277ca3df56fe9418a5913d9188eafe3bc development | something1 something2 something3',
trigger,
noop_trigger,
+ destroy_trigger,
stable_branch
)
).toStrictEqual({
@@ -161,6 +171,7 @@ test('checks the comment body and finds an explicit environment target and an ex
environmentObj: {
target: 'development',
noop: true,
+ destroy: false,
stable_branch_used: false,
params: 'something1 something2 something3',
parsed_params: {_: ['something1', 'something2', 'something3']},
@@ -186,6 +197,7 @@ test('checks the comment body and finds an explicit environment target and an ex
'.noop 82c238c277ca3df56fe9418a5913d9188eafe3bc development | --cpu=2 --memory=4G --env=development --port=8080 --name=my-app -q my-queue',
trigger,
noop_trigger,
+ destroy_trigger,
stable_branch
)
).toStrictEqual({
@@ -194,6 +206,7 @@ test('checks the comment body and finds an explicit environment target and an ex
environmentObj: {
target: 'development',
noop: true,
+ destroy: false,
stable_branch_used: false,
params:
'--cpu=2 --memory=4G --env=development --port=8080 --name=my-app -q my-queue',
@@ -228,6 +241,7 @@ test('checks the comment body and finds an explicit environment target and an ex
'.noop f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b development | something1 something2 something3',
trigger,
noop_trigger,
+ destroy_trigger,
stable_branch
)
).toStrictEqual({
@@ -236,6 +250,7 @@ test('checks the comment body and finds an explicit environment target and an ex
environmentObj: {
target: 'development',
noop: true,
+ destroy: false,
stable_branch_used: false,
params: 'something1 something2 something3',
parsed_params: {_: ['something1', 'something2', 'something3']},
@@ -261,6 +276,7 @@ test('checks the comment body and finds an explicit environment target and an ex
'.noop 82c238c277ca3df56fe9418a5913d9188eafe3bc ',
trigger,
noop_trigger,
+ destroy_trigger,
stable_branch
)
).toStrictEqual({
@@ -269,6 +285,7 @@ test('checks the comment body and finds an explicit environment target and an ex
environmentObj: {
target: 'production',
noop: true,
+ destroy: false,
stable_branch_used: false,
params: null,
parsed_params: null,
@@ -289,6 +306,7 @@ test('checks the comment body and finds an explicit environment target for devel
'.deploy main development + something1 | something2 something3',
trigger,
noop_trigger,
+ destroy_trigger,
stable_branch,
null,
null,
@@ -303,6 +321,7 @@ test('checks the comment body and finds an explicit environment target for devel
environmentObj: {
target: 'development',
noop: false,
+ destroy: false,
stable_branch_used: true,
params: 'something1 | something2 something3',
parsed_params: {_: ['something1', '|', 'something2', 'something3']},
@@ -328,6 +347,7 @@ test('checks the comment body and finds an explicit environment target for stagi
'.noop staging',
trigger,
noop_trigger,
+ destroy_trigger,
stable_branch
)
).toStrictEqual({
@@ -336,6 +356,7 @@ test('checks the comment body and finds an explicit environment target for stagi
environmentObj: {
target: 'staging',
noop: true,
+ destroy: false,
stable_branch_used: false,
params: null,
parsed_params: null,
@@ -354,6 +375,7 @@ test('checks the comment body and finds an explicit environment target for stagi
'.noop main staging',
trigger,
noop_trigger,
+ destroy_trigger,
stable_branch
)
).toStrictEqual({
@@ -362,6 +384,7 @@ test('checks the comment body and finds an explicit environment target for stagi
environmentObj: {
target: 'staging',
noop: true,
+ destroy: false,
stable_branch_used: true,
params: null,
parsed_params: null,
@@ -380,6 +403,7 @@ test('checks the comment body and finds an explicit environment target for stagi
'.noop staging',
trigger,
noop_trigger,
+ destroy_trigger,
stable_branch,
null,
null,
@@ -393,6 +417,7 @@ test('checks the comment body and finds an explicit environment target for stagi
environmentObj: {
target: 'staging',
noop: true,
+ destroy: false,
stable_branch_used: false,
params: null,
parsed_params: null,
@@ -424,6 +449,7 @@ test('checks the comment body and finds an explicit environment target for stagi
'.noop main to staging | something1 something2 something3',
trigger,
noop_trigger,
+ destroy_trigger,
stable_branch,
null,
null,
@@ -437,6 +463,7 @@ test('checks the comment body and finds an explicit environment target for stagi
environmentObj: {
target: 'staging',
noop: true,
+ destroy: false,
stable_branch_used: true,
params: 'something1 something2 something3',
parsed_params: {_: ['something1', 'something2', 'something3']},
@@ -473,6 +500,7 @@ test('checks the comment body and uses the default production environment target
'.deploy',
trigger,
noop_trigger,
+ destroy_trigger,
stable_branch,
null,
null,
@@ -486,6 +514,7 @@ test('checks the comment body and uses the default production environment target
environmentObj: {
target: 'production',
noop: false,
+ destroy: false,
stable_branch_used: false,
params: null,
parsed_params: null,
@@ -515,6 +544,7 @@ test('checks the comment body and finds an explicit environment target for a pro
'.deploy production',
trigger,
noop_trigger,
+ destroy_trigger,
stable_branch,
null,
null,
@@ -528,6 +558,7 @@ test('checks the comment body and finds an explicit environment target for a pro
environmentObj: {
target: 'production',
noop: false,
+ destroy: false,
params: null,
parsed_params: null,
stable_branch_used: false,
@@ -551,6 +582,7 @@ test('checks the comment body and finds an explicit environment target for a pro
'.deploy production',
trigger,
noop_trigger,
+ destroy_trigger,
stable_branch,
null,
null,
@@ -565,6 +597,7 @@ test('checks the comment body and finds an explicit environment target for a pro
target: 'production',
stable_branch_used: false,
noop: false,
+ destroy: false,
params: null,
parsed_params: null,
sha: null
@@ -590,6 +623,7 @@ test('checks the comment body and finds an explicit environment target for a pro
'.deploy production',
trigger,
noop_trigger,
+ destroy_trigger,
stable_branch,
null,
null,
@@ -604,6 +638,7 @@ test('checks the comment body and finds an explicit environment target for a pro
target: 'production',
stable_branch_used: false,
noop: false,
+ destroy: false,
params: null,
parsed_params: null,
sha: null
@@ -626,6 +661,7 @@ test('checks the comment body and finds an explicit environment target for stagi
'.noop to staging',
trigger,
noop_trigger,
+ destroy_trigger,
stable_branch
)
).toStrictEqual({
@@ -635,6 +671,7 @@ test('checks the comment body and finds an explicit environment target for stagi
target: 'staging',
stable_branch_used: false,
noop: true,
+ destroy: false,
params: null,
parsed_params: null,
sha: null
@@ -652,6 +689,7 @@ test('checks the comment body and finds a noop deploy to the stable branch and d
'.noop main',
trigger,
noop_trigger,
+ destroy_trigger,
stable_branch
)
).toStrictEqual({
@@ -661,6 +699,7 @@ test('checks the comment body and finds a noop deploy to the stable branch and d
target: 'production',
stable_branch_used: true,
noop: true,
+ destroy: false,
params: null,
parsed_params: null,
sha: null
@@ -678,6 +717,7 @@ test('checks the comment body and finds a noop deploy to the stable branch and d
'.noop main | foo=bar',
trigger,
noop_trigger,
+ destroy_trigger,
stable_branch
)
).toStrictEqual({
@@ -687,6 +727,7 @@ test('checks the comment body and finds a noop deploy to the stable branch and d
target: 'production',
stable_branch_used: true,
noop: true,
+ destroy: false,
params: 'foo=bar',
parsed_params: {_: ['foo=bar']},
sha: null
@@ -704,6 +745,7 @@ test('checks the comment body and finds an explicit environment target for produ
'.deploy to production',
trigger,
noop_trigger,
+ destroy_trigger,
stable_branch
)
).toStrictEqual({
@@ -713,6 +755,7 @@ test('checks the comment body and finds an explicit environment target for produ
target: 'production',
stable_branch_used: false,
noop: false,
+ destroy: false,
params: null,
parsed_params: null,
sha: null
@@ -730,6 +773,7 @@ test('checks the comment body on a noop deploy and does not find an explicit env
'.noop', // comment body
trigger,
noop_trigger,
+ destroy_trigger,
stable_branch
)
).toStrictEqual({
@@ -739,6 +783,7 @@ test('checks the comment body on a noop deploy and does not find an explicit env
target: 'production',
stable_branch_used: false,
noop: true,
+ destroy: false,
params: null,
parsed_params: null,
sha: null
@@ -756,6 +801,7 @@ test('checks the comment body on a deployment and does not find any matching env
'.deploy to chaos',
trigger,
noop_trigger,
+ destroy_trigger,
stable_branch
)
).toStrictEqual({
@@ -763,6 +809,7 @@ test('checks the comment body on a deployment and does not find any matching env
environmentUrl: null,
environmentObj: {
noop: null,
+ destroy: null,
params: null,
parsed_params: null,
stable_branch_used: null,
@@ -788,6 +835,7 @@ test('checks the comment body on a stable branch deployment and finds a matching
'.deploy main to production',
trigger,
noop_trigger,
+ destroy_trigger,
stable_branch
)
).toStrictEqual({
@@ -797,6 +845,7 @@ test('checks the comment body on a stable branch deployment and finds a matching
target: 'production',
stable_branch_used: true,
noop: false,
+ destroy: false,
params: null,
parsed_params: null,
sha: null
@@ -814,6 +863,7 @@ test('checks the comment body on a stable branch deployment and finds a matching
'.deploy main production',
trigger,
noop_trigger,
+ destroy_trigger,
stable_branch
)
).toStrictEqual({
@@ -823,6 +873,7 @@ test('checks the comment body on a stable branch deployment and finds a matching
target: 'production',
stable_branch_used: true,
noop: false,
+ destroy: false,
params: null,
parsed_params: null,
sha: null
@@ -840,6 +891,7 @@ test('checks the comment body on a stable branch deployment and uses the default
'.deploy main',
trigger,
noop_trigger,
+ destroy_trigger,
stable_branch
)
).toStrictEqual({
@@ -849,6 +901,7 @@ test('checks the comment body on a stable branch deployment and uses the default
target: 'production',
stable_branch_used: true,
noop: false,
+ destroy: false,
params: null,
parsed_params: null,
sha: null
@@ -866,6 +919,7 @@ test('checks the comment body on a stable branch deployment and does not find a
'.deploy main chaos',
trigger,
noop_trigger,
+ destroy_trigger,
stable_branch
)
).toStrictEqual({
@@ -873,6 +927,7 @@ test('checks the comment body on a stable branch deployment and does not find a
environmentUrl: null,
environmentObj: {
noop: null,
+ destroy: null,
params: null,
parsed_params: null,
stable_branch_used: null,
@@ -898,6 +953,7 @@ test('checks the comment body on a lock request and uses the default environment
'.lock', // comment body
'.lock', // lock trigger
'.unlock', // unlock trigger
+ '.destroy', // destroy trigger
null, // stable_branch not used for lock/unlock requests
null, // context
null, // octokit
@@ -917,6 +973,7 @@ test('checks the comment body on a lock request with a reason and uses the defau
'.lock --reason making a small change to our api because reasons', // comment body
'.lock', // lock trigger
'.unlock', // unlock trigger
+ '.destroy', // destroy trigger
null, // stable_branch not used for lock/unlock requests
null, // context
null, // octokit
@@ -936,6 +993,7 @@ test('checks the comment body on a lock request with a reason and uses the expli
'.lock production --reason small change to mappings for risk rating - - 92*91-2408| ', // comment body
'.lock', // lock trigger
'.unlock', // unlock trigger
+ '.destroy', // destroy trigger
null, // stable_branch not used for lock/unlock requests
null, // context
null, // octokit
@@ -955,6 +1013,7 @@ test('checks the comment body on an unlock request and uses the default environm
'.unlock', // comment body
'.lock', // lock trigger
'.unlock', // unlock trigger
+ '.destroy', // destroy trigger
null, // stable_branch not used for lock/unlock requests
null, // context
null, // octokit
@@ -974,6 +1033,7 @@ test('checks the comment body on an unlock request and uses the default environm
'.unlock --reason oh wait this command does not need a reason.. oops', // comment body
'.lock', // lock trigger
'.unlock', // unlock trigger
+ '.destroy', // destroy trigger
null, // stable_branch not used for lock/unlock requests
null, // context
null, // octokit
@@ -993,6 +1053,7 @@ test('checks the comment body on an unlock request and uses the development envi
'.unlock development --reason oh wait this command does not need a reason.. oops', // comment body
'.lock', // lock trigger
'.unlock', // unlock trigger
+ '.destroy', // destroy trigger
null, // stable_branch not used for lock/unlock requests
null, // context
null, // octokit
@@ -1012,6 +1073,7 @@ test('checks the comment body on a lock info alias request and uses the default
'.wcid', // comment body
'.lock', // lock trigger
'.unlock', // unlock trigger
+ '.destroy', // destroy trigger
null, // stable_branch not used for lock/unlock requests
null, // context
null, // octokit
@@ -1031,6 +1093,7 @@ test('checks the comment body on a lock request and uses the production environm
'.lock production', // comment body
'.lock', // lock trigger
'.unlock', // unlock trigger
+ '.destroy', // destroy trigger
null, // stable_branch not used for lock/unlock requests
null, // context
null, // octokit
@@ -1050,6 +1113,7 @@ test('checks the comment body on an unlock request and uses the development envi
'.unlock development', // comment body
'.lock', // lock trigger
'.unlock', // unlock trigger
+ '.destroy', // destroy trigger
null, // stable_branch not used for lock/unlock requests
null, // context
null, // octokit
@@ -1069,6 +1133,7 @@ test('checks the comment body on a lock info alias request and uses the developm
'.wcid development', // comment body
'.lock', // lock trigger
'.unlock', // unlock trigger
+ '.destroy', // destroy trigger
null, // stable_branch not used for lock/unlock requests
null, // context
null, // octokit
@@ -1088,6 +1153,7 @@ test('checks the comment body on a lock info request and uses the development en
'.lock --info development', // comment body
'.lock', // lock trigger
'.unlock', // unlock trigger
+ '.destroy', // destroy trigger
null, // stable_branch not used for lock/unlock requests
null, // context
null, // octokit
@@ -1107,6 +1173,7 @@ test('checks the comment body on a lock info request and uses the development en
'.lock -d development', // comment body
'.lock', // lock trigger
'.unlock', // unlock trigger
+ '.destroy', // destroy trigger
null, // stable_branch not used for lock/unlock requests
null, // context
null, // octokit
diff --git a/__tests__/main.test.js b/__tests__/main.test.js
index 5bf83e77..12f3b02b 100644
--- a/__tests__/main.test.js
+++ b/__tests__/main.test.js
@@ -71,6 +71,7 @@ beforeEach(() => {
process.env.INPUT_PRODUCTION_ENVIRONMENTS = 'production'
process.env.INPUT_STABLE_BRANCH = 'main'
process.env.INPUT_NOOP_TRIGGER = '.noop'
+ process.env.INPUT_DESTROY_TRIGGER = '.destroy'
process.env.INPUT_LOCK_TRIGGER = '.lock'
process.env.INPUT_UNLOCK_TRIGGER = '.unlock'
process.env.INPUT_HELP_TRIGGER = '.help'
diff --git a/badges/coverage.svg b/badges/coverage.svg
index 1b3eb315..f20a65f6 100644
--- a/badges/coverage.svg
+++ b/badges/coverage.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/functions/deployment-confirmation.js b/src/functions/deployment-confirmation.js
index f31f2e2c..41fa6f95 100644
--- a/src/functions/deployment-confirmation.js
+++ b/src/functions/deployment-confirmation.js
@@ -37,6 +37,7 @@ export async function deploymentConfirmation(context, octokit, data) {
"url": ${data.environmentUrl ? `"${data.environmentUrl}"` : null}
},
"deployment": {
+ "type": "${data.deploymentApiType}",
"logs": "${data.log_url}"
},
"git": {
diff --git a/src/functions/environment-targets.js b/src/functions/environment-targets.js
index c276d45b..7dd17d85 100644
--- a/src/functions/environment-targets.js
+++ b/src/functions/environment-targets.js
@@ -11,6 +11,7 @@ import {parseParams} from './params'
// :param body: The body of the comment
// :param trigger: The trigger used to initiate the deployment
// :param noop_trigger: The trigger used to initiate a noop deployment
+// :param destroy_trigger: The trigger used to initiate a destroy deployment
// :param stable_branch: The stable branch
// :param environment: The default environment
// :param param_separator: The separator used to seperate the command from the parameters
@@ -20,6 +21,7 @@ async function onDeploymentChecks(
body,
trigger,
noop_trigger,
+ destroy_trigger,
stable_branch,
environment,
param_separator
@@ -71,9 +73,18 @@ async function onDeploymentChecks(
`${escapedNoopTrigger}\\s+((?![a-f0-9]{40}[a-f0-9]{24})[a-f0-9]{40}|[a-f0-9]{64})`,
'i'
)
+ const escapedDestroyTrigger = destroy_trigger.replace(
+ /[-[\]/{}()*+?.\\^$|]/g,
+ '\\$&'
+ )
+ const destroyRegex = new RegExp(
+ `${escapedDestroyTrigger}\\s+((?![a-f0-9]{40}[a-f0-9]{24})[a-f0-9]{40}|[a-f0-9]{64})`,
+ 'i'
+ )
const match = bodyFmt.trim().match(regex)
const noopMatch = bodyFmt.trim().match(noopRegex)
+ const destroyMatch = bodyFmt.trim().match(destroyRegex)
if (match) {
sha = match[1] // The captured SHA value
// if a sha was used, then we need to remove it from the body for env checks
@@ -88,6 +99,15 @@ async function onDeploymentChecks(
core.info(
`📍 detected SHA in noop command: ${COLORS.highlight}${sha}${COLORS.reset}`
)
+ } else if (destroyMatch) {
+ sha = destroyMatch[1] // The captured SHA value
+ // if a sha was used, then we need to remove it from the body for env checks
+ bodyFmt = bodyFmt.replace(new RegExp(`\\s*${sha}\\s*`, 'g'), '').trim()
+ core.info(
+ `📍 detected SHA in destroy command: ${COLORS.highlight}${sha}${COLORS.reset}`
+ )
+ } else {
+ core.debug('no SHA detected in command')
}
// Loop through all the environment targets to see if an explicit target is being used
@@ -99,6 +119,7 @@ async function onDeploymentChecks(
target: target,
stable_branch_used: false,
noop: false,
+ destroy: false,
params: paramsTrim,
parsed_params: parsed_params,
sha: sha
@@ -111,6 +132,20 @@ async function onDeploymentChecks(
target: target,
stable_branch_used: false,
noop: true,
+ destroy: false,
+ params: paramsTrim,
+ parsed_params: parsed_params,
+ sha: sha
+ }
+ }
+ // If the body on a destroy trigger contains the target
+ else if (bodyFmt.replace(destroy_trigger, '').trim() === target) {
+ core.debug(`found environment target for destroy trigger: ${target}`)
+ return {
+ target: target,
+ stable_branch_used: false,
+ noop: false,
+ destroy: true,
params: paramsTrim,
parsed_params: parsed_params,
sha: sha
@@ -125,6 +160,7 @@ async function onDeploymentChecks(
target: target,
stable_branch_used: false,
noop: false,
+ destroy: false,
params: paramsTrim,
parsed_params: parsed_params,
sha: sha
@@ -139,6 +175,22 @@ async function onDeploymentChecks(
target: target,
stable_branch_used: false,
noop: true,
+ destroy: false,
+ params: paramsTrim,
+ parsed_params: parsed_params,
+ sha: sha
+ }
+ }
+ // If the body with 'to ' contains the target on a destroy trigger
+ else if (bodyFmt.replace(destroy_trigger, '').trim() === `to ${target}`) {
+ core.debug(
+ `found environment target for destroy trigger (with 'to'): ${target}`
+ )
+ return {
+ target: target,
+ stable_branch_used: false,
+ noop: false,
+ destroy: true,
params: paramsTrim,
parsed_params: parsed_params,
sha: sha
@@ -156,6 +208,7 @@ async function onDeploymentChecks(
target: target,
stable_branch_used: true,
noop: false,
+ destroy: false,
params: paramsTrim,
parsed_params: parsed_params,
sha: sha
@@ -173,6 +226,26 @@ async function onDeploymentChecks(
target: target,
stable_branch_used: true,
noop: true,
+ destroy: false,
+ params: paramsTrim,
+ parsed_params: parsed_params,
+ sha: sha
+ }
+ }
+ // If the body with 'to ' contains the target on a stable branch destroy trigger
+ else if (
+ bodyFmt.replace(`${destroy_trigger} ${stable_branch}`, '').trim() ===
+ `to ${target}`
+ ) {
+ core.debug(
+ `found environment target for stable branch destroy trigger (with 'to'): ${target}`
+ )
+ core.info(`🤠 Whoa partner! A ${COLORS.highlight}destroy${COLORS.reset} command to the ${COLORS.highlight}${stable_branch}${COLORS.reset} branch?! That takes some confidence. You are BOLD.`)
+ return {
+ target: target,
+ stable_branch_used: true,
+ noop: false,
+ destroy: true,
params: paramsTrim,
parsed_params: parsed_params,
sha: sha
@@ -187,6 +260,7 @@ async function onDeploymentChecks(
target: target,
stable_branch_used: true,
noop: false,
+ destroy: false,
params: paramsTrim,
parsed_params: parsed_params,
sha: sha
@@ -203,6 +277,26 @@ async function onDeploymentChecks(
target: target,
stable_branch_used: true,
noop: true,
+ destroy: false,
+ params: paramsTrim,
+ parsed_params: parsed_params,
+ sha: sha
+ }
+ }
+ // If the body on a stable branch destroy trigger contains the target
+ else if (
+ bodyFmt.replace(`${destroy_trigger} ${stable_branch}`, '').trim() ===
+ target
+ ) {
+ core.debug(
+ `found environment target for stable branch destroy trigger: ${target}`
+ )
+ core.info(`🤠 Whoa partner! A ${COLORS.highlight}destroy${COLORS.reset} command to the ${COLORS.highlight}${stable_branch}${COLORS.reset} branch?! That takes some confidence. You are BOLD.`)
+ return {
+ target: target,
+ stable_branch_used: true,
+ noop: false,
+ destroy: true,
params: paramsTrim,
parsed_params: parsed_params,
sha: sha
@@ -215,6 +309,7 @@ async function onDeploymentChecks(
target: environment,
stable_branch_used: false,
noop: false,
+ destroy: false,
params: paramsTrim,
parsed_params: parsed_params,
sha: sha
@@ -227,6 +322,20 @@ async function onDeploymentChecks(
target: environment,
stable_branch_used: false,
noop: true,
+ destroy: false,
+ params: paramsTrim,
+ parsed_params: parsed_params,
+ sha: sha
+ }
+ }
+ // If the body matches the destroy_trigger phrase exactly, just use the default environment
+ else if (bodyFmt.trim() === destroy_trigger) {
+ core.debug('using default environment for destroy trigger')
+ return {
+ target: environment,
+ stable_branch_used: false,
+ noop: false,
+ destroy: true,
params: paramsTrim,
parsed_params: parsed_params,
sha: sha
@@ -239,6 +348,7 @@ async function onDeploymentChecks(
target: environment,
stable_branch_used: true,
noop: false,
+ destroy: false,
params: paramsTrim,
parsed_params: parsed_params,
sha: sha
@@ -251,6 +361,21 @@ async function onDeploymentChecks(
target: environment,
stable_branch_used: true,
noop: true,
+ destroy: false,
+ params: paramsTrim,
+ parsed_params: parsed_params,
+ sha: sha
+ }
+ }
+ // If the body matches the stable branch phrase exactly on a destroy trigger, just use the default environment
+ else if (bodyFmt.trim() === `${destroy_trigger} ${stable_branch}`) {
+ core.debug('using default environment for stable branch destroy trigger')
+ core.info(`🤠 Whoa partner! A ${COLORS.highlight}destroy${COLORS.reset} command to the ${COLORS.highlight}${stable_branch}${COLORS.reset} branch?! That takes some confidence. You are BOLD.`)
+ return {
+ target: environment,
+ stable_branch_used: true,
+ noop: false,
+ destroy: true,
params: paramsTrim,
parsed_params: parsed_params,
sha: sha
@@ -263,6 +388,7 @@ async function onDeploymentChecks(
target: false,
stable_branch_used: null,
noop: null,
+ destroy: null,
params: null,
parsed_params: null,
sha: null
@@ -274,6 +400,7 @@ async function onDeploymentChecks(
// :param body: The body of the comment
// :param lock_trigger: The trigger used to initiate the lock command
// :param unlock_trigger: The trigger used to initiate the unlock command
+// :param destroy_trigger: The trigger used to initiate the destroy command
// :param environment: The default environment from the Actions inputs
// :returns: The environment target if found, false otherwise
async function onLockChecks(
@@ -281,6 +408,7 @@ async function onLockChecks(
body,
lock_trigger,
unlock_trigger,
+ destroy_trigger,
environment
) {
// if the body contains the globalFlag, exit right away as environments are not relevant
@@ -319,6 +447,12 @@ async function onLockChecks(
return environment
}
+ // if the body matches the destroy trigger exactly, just use the default environment
+ if (body.trim() === destroy_trigger.trim()) {
+ core.debug('using default environment for destroy request')
+ return environment
+ }
+
// if the body matches the lock info alias exactly, just use the default environment
if (body.trim() === lockInfoAlias.trim()) {
core.debug('using default environment for lock info request')
@@ -334,6 +468,9 @@ async function onLockChecks(
} else if (body.replace(unlock_trigger, '').trim() === target) {
core.debug(`found environment target for unlock request: ${target}`)
return target
+ } else if (body.replace(destroy_trigger, '').trim() === target) {
+ core.debug(`found environment target for destroy request: ${target}`)
+ return target
} else if (body.replace(lockInfoAlias, '').trim() === target) {
core.debug(`found environment target for lock info request: ${target}`)
return target
@@ -406,6 +543,7 @@ async function findEnvironmentUrl(environment, environment_urls) {
// :param body: The comment body
// :param trigger: The trigger prefix
// :param alt_trigger: Usually the noop trigger prefix
+// :param destroy_trigger: The destroy trigger prefix
// :param stable_branch: The stable branch (only used for branch deploys)
// :param context: The context of the Action
// :param octokit: The Octokit instance
@@ -419,6 +557,7 @@ export async function environmentTargets(
body,
trigger,
alt_trigger,
+ destroy_trigger,
stable_branch,
context,
octokit,
@@ -445,6 +584,7 @@ export async function environmentTargets(
body,
trigger,
alt_trigger,
+ destroy_trigger,
environment
)
if (environmentDetected !== false) {
@@ -476,6 +616,7 @@ export async function environmentTargets(
body,
trigger,
alt_trigger,
+ destroy_trigger,
stable_branch,
environment,
param_separator
diff --git a/src/functions/inputs.js b/src/functions/inputs.js
index 1e8835d7..4022aea6 100644
--- a/src/functions/inputs.js
+++ b/src/functions/inputs.js
@@ -35,6 +35,7 @@ export function getInputs() {
const stable_branch = core.getInput('stable_branch')
const noop_trigger = core.getInput('noop_trigger')
const lock_trigger = core.getInput('lock_trigger')
+ const destroy_trigger = core.getInput('destroy_trigger')
const production_environments = stringToArray(
core.getInput('production_environments')
)
@@ -99,6 +100,7 @@ export function getInputs() {
stable_branch: stable_branch,
noop_trigger: noop_trigger,
lock_trigger: lock_trigger,
+ destroy_trigger: destroy_trigger,
production_environments: production_environments,
environment_targets: environment_targets,
unlock_trigger: unlock_trigger,
diff --git a/src/main.js b/src/main.js
index 6dc38e25..5db812bf 100644
--- a/src/main.js
+++ b/src/main.js
@@ -98,6 +98,7 @@ export async function run() {
[
inputs.trigger,
inputs.noop_trigger,
+ inputs.destroy_trigger,
inputs.lock_trigger,
inputs.unlock_trigger,
inputs.lock_info_alias
@@ -120,13 +121,16 @@ export async function run() {
// check if the comment is a trigger and what type of trigger it is
const isDeploy = await triggerCheck(body, inputs.trigger)
+ const isDestroy = await triggerCheck(body, inputs.destroy_trigger)
const isNoopDeploy = await triggerCheck(body, inputs.noop_trigger)
const isLock = await triggerCheck(body, inputs.lock_trigger)
const isUnlock = await triggerCheck(body, inputs.unlock_trigger)
const isHelp = await triggerCheck(body, inputs.help_trigger)
const isLockInfoAlias = await triggerCheck(body, inputs.lock_info_alias)
- if (isDeploy || isNoopDeploy) {
+ if (isDeploy || isNoopDeploy || isDestroy) {
+ // deployments, noops, and destroy commands are all treated as "deployment events"
+ // yes, even destroy commands because they are the same as a .deploy command but with one extra output set
core.setOutput('type', 'deploy')
} else if (isLock) {
core.setOutput('type', 'lock')
@@ -144,6 +148,12 @@ export async function run() {
return 'safe-exit'
}
+ if (isDestroy) {
+ core.info(`🗑️ destroy command detected`)
+ core.setOutput('destroy', 'true')
+ core.saveState('destroy', 'true')
+ }
+
// If we made it this far, the action has been triggered in one manner or another
core.setOutput('triggered', 'true')
@@ -390,6 +400,7 @@ export async function run() {
body, // comment body
inputs.trigger, // trigger
inputs.noop_trigger, // noop trigger
+ inputs.destroy_trigger, // destroy trigger
inputs.stable_branch, // ref
context, // context object
octokit, // octokit object
@@ -607,12 +618,18 @@ export async function run() {
// Add a comment to the PR letting the user know that a deployment has been started
// Format the success message
+ var deploymentApiType
var deploymentType
if (precheckResults.noopMode) {
deploymentType = 'noop'
+ deploymentApiType = 'noop'
+ } else if (isDestroy) {
+ deploymentType = 'destroy'
+ deploymentApiType = 'destroy'
} else {
deploymentType =
environmentObj.environmentObj.sha !== null ? 'sha' : 'branch'
+ deploymentApiType = 'deploy'
}
const log_url = `${process.env.GITHUB_SERVER_URL}/${context.repo.owner}/${context.repo.repo}/actions/runs/${github_run_id}`
@@ -625,6 +642,7 @@ export async function run() {
sha: precheckResults.sha,
ref: precheckResults.ref,
deploymentType: deploymentType,
+ deploymentApiType: deploymentApiType,
environment: environment,
environmentUrl: environmentObj.environmentUrl,
deployment_confirmation_timeout:
@@ -680,6 +698,7 @@ export async function run() {
"url": ${environmentObj.environmentUrl ? `"${environmentObj.environmentUrl}"` : null}
},
"deployment": {
+ "type": "${deploymentApiType}",
"timestamp": "${deployment_start_time}",
"logs": "${log_url}"
},
@@ -776,6 +795,7 @@ export async function run() {
// Construct the deployment payload that will be sent to the GitHub API during the deployment creation
const payload = {
type: 'branch-deploy',
+ deployment_type: deploymentApiType,
sha: precheckResults.sha,
params: params,
parsed_params: parsed_params,
@@ -857,6 +877,8 @@ export async function run() {
core.saveState('bypass', 'true')
core.error(error.stack)
core.setFailed(error.message)
+ console.log(error.message)
+ console.log(error.stack)
}
}