From 3e9715dcb514770c2573958e835b64dcba04312b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Test=C3=A9?= Date: Wed, 4 Dec 2024 15:21:02 +0100 Subject: [PATCH] WIP: try to handle cancellation --- .github/workflows/test_start_stop.yml | 74 +++++++++++++-------------- dist/index.js | 45 ++++++++++++++++ src/index.js | 17 ++++++ src/slab.js | 28 ++++++++++ 4 files changed, 127 insertions(+), 37 deletions(-) diff --git a/.github/workflows/test_start_stop.yml b/.github/workflows/test_start_stop.yml index c054624..f9a817e 100644 --- a/.github/workflows/test_start_stop.yml +++ b/.github/workflows/test_start_stop.yml @@ -40,40 +40,40 @@ jobs: job-secret: ${{ secrets.JOB_SECRET }} backend: aws profile: ci-test-start-stop - - test-runner-alive: - name: Test runner is alive - needs: [ action-start ] - uses: ./.github/workflows/registered_runner.yml - with: - runner-name: ci-persistent-runner - - action-stop: - name: GitHub Actions Test (stop) - runs-on: ubuntu-latest - needs: [ action-start, test-runner-alive ] - if: ${{ always() && needs.action-start.result != 'skipped' }} - steps: - - name: Checkout - id: checkout - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 - - - name: Test stop instance - id: test-stop - uses: ./ - with: - mode: stop - github-token: ${{ secrets.SLAB_ACTION_TOKEN }} - slab-url: ${{ secrets.SLAB_BASE_URL_PRE_PROD }} - job-secret: ${{ secrets.JOB_SECRET }} - label: ci-persistent-runner - - test-runner-persist: - name: Test runner is still registered - needs: [ action-stop ] - uses: ./.github/workflows/removed_runner.yml - with: - runner-name: ci-persistent-runner - must-exist: true - secrets: - READ_REPO_TOKEN: ${{ secrets.SLAB_ACTION_TOKEN }} +# +# test-runner-alive: +# name: Test runner is alive +# needs: [ action-start ] +# uses: ./.github/workflows/registered_runner.yml +# with: +# runner-name: ci-persistent-runner +# +# action-stop: +# name: GitHub Actions Test (stop) +# runs-on: ubuntu-latest +# needs: [ action-start, test-runner-alive ] +# if: ${{ always() && needs.action-start.result != 'skipped' }} +# steps: +# - name: Checkout +# id: checkout +# uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 +# +# - name: Test stop instance +# id: test-stop +# uses: ./ +# with: +# mode: stop +# github-token: ${{ secrets.SLAB_ACTION_TOKEN }} +# slab-url: ${{ secrets.SLAB_BASE_URL_PRE_PROD }} +# job-secret: ${{ secrets.JOB_SECRET }} +# label: ci-persistent-runner +# +# test-runner-persist: +# name: Test runner is still registered +# needs: [ action-stop ] +# uses: ./.github/workflows/removed_runner.yml +# with: +# runner-name: ci-persistent-runner +# must-exist: true +# secrets: +# READ_REPO_TOKEN: ${{ secrets.SLAB_ACTION_TOKEN }} diff --git a/dist/index.js b/dist/index.js index 4abb551..d84e1a0 100644 --- a/dist/index.js +++ b/dist/index.js @@ -49835,6 +49835,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') { @@ -49900,6 +49903,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, @@ -51855,11 +51883,27 @@ const slab = __nccwpck_require__(4156) const config = __nccwpck_require__(4570) const core = __nccwpck_require__(2186) const { waitForRunnerRegistered } = __nccwpck_require__(6989) +const utils = __nccwpck_require__(1608) 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 @@ -51868,6 +51912,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...') diff --git a/src/index.js b/src/index.js index 57019a7..735fcad 100644 --- a/src/index.js +++ b/src/index.js @@ -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 @@ -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...') diff --git a/src/slab.js b/src/slab.js index e07586b..71e4261 100644 --- a/src/slab.js +++ b/src/slab.js @@ -127,6 +127,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') { @@ -192,6 +195,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,