Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Intercept GitHub Workflow Cancellation on Docker Container

I am running tests on GitHub Actions using a Workflow that uses a custom Docker image I've created.

When cancelling the Workflow, GitHub kills the docker container as per documentation.

Is there a way to intercept the "kill" of the container so that I could run some teardown commands in the container before terminating it?

like image 349
Ben Avatar asked Apr 15 '26 21:04

Ben


1 Answers

It is possible at least by defining a custom action with a custom entrypoint script.

While you cannot use --entrypoint in default containerized action (as noted here), you can create your own action and define an entrypoint script where you can trap the SIGINT GitHub send to the container:

For steps that need to be canceled, the runner machine sends SIGINT/Ctrl-C to the step's entry process (docker for container action). If the process doesn't exit within 7500 ms, the runner will send SIGTERM/Ctrl-Break to the process, then wait for 2500 ms for the process to exit. If the process is still running, the runner kills the process tree.

Custom action

Here's an example of a custom action in my repository. I have the following structure:

repository
├── .github
│   ├── actions
│   │   └── test-teri
│   │       ├── Dockerfile
│   │       ├── action.yml
│   │       └── entrypoint.sh
│   └── workflows
│       └── cd_workflow.yml

The Dockerfile is just a copy from GH actions documentation.

FROM alpine:3.10

COPY entrypoint.sh /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]

In entrypoint.sh I have the beef of the process:

#!/bin/sh -l

trap cleanup SIGINT

cleanup() {
    sleep 2
    echo "Cleanup successful."
    exit
}

while true
do
    echo "Testing..."
    sleep 1
done

I'm trapping the SIGINT signal within the entrypoint and calling the cleanup function when that happens. This script just normally prints Testing... infinitely to the output, but you can define your entrypoint in a way that it calls other stuff based on your run: instruction in workflow or however you want. I won't go into detail on that.

Remember to give execution permissions to the entrypoint sript, otherwise it won't run.

Finally, my action.yml, where you define the Dockerfile used to run this action.

# action.yml
name: 'Hello World'
description: 'Test sigint'
runs:
  using: 'docker'
  image: 'Dockerfile'

Running the workflow

Then, you just need to use this custom action in your workflow.

name: Test

on:
  push:
    branches:
      - so-test # <- Whatever branch you are using

jobs:
  build:
    name: "SO test build"
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Test action with sigint
        uses: ./.github/actions/test-teri

Testing sigint

Now when I run the workflow and cancel it after a while, the following can be seen in the log:

Testing...
Testing...
Testing...
Testing...
Testing...
Testing...
Testing...
Cleanup successful.
Error: The operation was canceled.

You notice that the cleanup function has been executed. But do notice that the time limit to run that is that 7500ms, so it needs to succeed in that time. I'm not aware if you can customize that time in any way in GH actions.

like image 155
Teemu Risikko Avatar answered Apr 18 '26 11:04

Teemu Risikko



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!