Skip to content

Commit

Permalink
feat(action): handle user cancellation
Browse files Browse the repository at this point in the history
This is useful in start mode where one can cancel before the
instance is actually ready. This way a best-effort is produced to
clean up any spawned instance instead of it turning into a zombie.
  • Loading branch information
soonum committed Dec 11, 2024
1 parent ff32326 commit 5a0942f
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 2 deletions.
48 changes: 47 additions & 1 deletion dist/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,27 @@ const slab = require('./slab')
const config = require('./config')
const core = require('@actions/core')
const { waitForRunnerRegistered } = require('./gh')
const utils = require('./utils')

function setOutput(label) {
core.setOutput('label', label)
}

// This variable should only be defined for cleanup purpose.
let runner_name

async function cleanup() {
if (runner_name) {
core.info('Stop instance after cancellation')
await slab.stopInstanceRequest(runner_name)
}
}

process.on('SIGINT', async function () {
await cleanup()
process.exit()
})

async function start() {
const provider = config.input.backend

Expand All @@ -15,6 +31,7 @@ async function start() {
for (let i = 1; i <= 3; i++) {
try {
start_instance_response = await slab.startInstanceRequest()
runner_name = start_instance_response.runner_name
break
} catch (error) {
core.info('Retrying request now...')
Expand Down
31 changes: 30 additions & 1 deletion src/slab.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ async function startInstanceRequest() {
const details = {
backend: {
provider,
profile: config.input.profile
profile: config.input.profile,
create_watchdog_task: true
}
}

Expand Down Expand Up @@ -127,6 +128,9 @@ async function waitForInstance(taskId, taskName) {
const task_status = body[taskName].status.toLowerCase()

if (task_status === 'done') {
if (taskName === 'start') {
await acknowledgeTaskDone(taskId)
}
await removeTask(taskId)
return body
} else if (task_status === 'failed') {
Expand Down Expand Up @@ -192,6 +196,31 @@ async function removeTask(taskId) {
}
}

async function acknowledgeTaskDone(taskId) {
const url = config.input.slabUrl
const route = `task_ack_done/${config.githubContext.repo}/${taskId}`
let response

try {
response = await fetch(concat_path(url, route), {
method: 'POST'
})
} catch (error) {
core.error(`Failed to acknowledge task done with ID: ${taskId}`)
throw error
}

if (response.ok) {
core.debug('Instance task successfully acknowledged')
return response
} else {
core.error(
`Instance task acknowledgment request has failed (ID: ${taskId}, HTTP status code: ${response.status})`
)
throw new Error('task acknowledging failed')
}
}

module.exports = {
startInstanceRequest,
stopInstanceRequest,
Expand Down

0 comments on commit 5a0942f

Please sign in to comment.