Skip to content

Commit

Permalink
Add stop-on-signals and auto-cancellation
Browse files Browse the repository at this point in the history
When workflows are cancelled, any started builds are left running. This
is not usually desired, for example if using workflow concurrency[^1] to
cancel redundant builds. In cases like this, we'd want to also stop any
triggered builds.

This commit adds a `stop-on-signals` input with a default value of
`SIGINT` and updates the action to listen for the listed signal(s) and
stop any already-started build in response. This accomplishes the
desired behavior in the common case.

[^1]: https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-concurrency-to-cancel-any-in-progress-job-or-run
  • Loading branch information
pbrisbin committed Jan 31, 2024
1 parent 8802399 commit 6fd170c
Show file tree
Hide file tree
Showing 4 changed files with 2,389 additions and 35,218 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,13 @@ The only required input is `project-name`.
1. **disable-github-env-vars** (optional) :
Set to `true` if you want do disable github environment variables in codebuild.

1. **stop-on-signals** (optional) :
Comma-separated list of signals that will cause any started builds to be
stopped. The default value is `SIGINT`, which is what GitHub sends processes
when a workflow is cancelled. This means you can use concurrency settings or
other GitHub features that cause workflow cancellations without leaving
orphan builds running. Set to an empty string to disable.

### Outputs

1. **aws-build-id** : The CodeBuild build ID of the build that the action ran.
Expand Down
4 changes: 4 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ inputs:
artifacts-type-override:
description: 'The type of build output artifact'
required: false
stop-on-signals:
description: 'Comma separated list of process signals on which to stop the build. Default is SIGINT.'
required: false
default: 'SIGINT'
outputs:
aws-build-id:
description: 'The AWS CodeBuild Build ID for this build.'
Expand Down
32 changes: 31 additions & 1 deletion code-build.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,16 @@ function runBuild() {

const inputs = githubInputs();

const config = (({ updateInterval, updateBackOff, hideCloudWatchLogs }) => ({
const config = (({
updateInterval,
updateBackOff,
hideCloudWatchLogs,
stopOnSignals,
}) => ({
updateInterval,
updateBackOff,
hideCloudWatchLogs,
stopOnSignals,
}))(inputs);

// Get input options for startBuild
Expand All @@ -39,10 +45,27 @@ async function build(sdk, params, config) {
// Start the build
const start = await sdk.codeBuild.startBuild(params);

// Set up signal handling to stop the build on cancellation
setupSignalHandlers(sdk, start.build.id, config.stopOnSignals);

// Wait for the build to "complete"
return waitForBuildEndTime(sdk, start.build, config);
}

function setupSignalHandlers(sdk, id, signals) {
signals.forEach((s) => {
core.info(`Installing signal handler for ${s}`);
process.on(s, async () => {
try {
core.info(`Caught ${s}, attempting to stop build...`);
await sdk.codeBuild.stopBuild({ id }).promise();
} catch (ex) {
core.error(`Error stopping build: ${ex}`);
}
});
});
}

async function waitForBuildEndTime(
sdk,
{ id, logs },
Expand Down Expand Up @@ -226,6 +249,12 @@ function githubInputs() {
const artifactsTypeOverride =
core.getInput("artifacts-type-override", { required: false }) || undefined;

const stopOnSignals = core
.getInput("stop-on-signals", { required: false })
.split(",")
.map((i) => i.trim())
.filter((i) => i !== "");

return {
projectName,
owner,
Expand All @@ -243,6 +272,7 @@ function githubInputs() {
hideCloudWatchLogs,
disableGithubEnvVars,
artifactsTypeOverride,
stopOnSignals,
};
}

Expand Down
Loading

0 comments on commit 6fd170c

Please sign in to comment.