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?
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.
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'
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With