我正在使用工作流程在 GitHub Actions 上运行测试,该工作流程使用我创建的 自定义 Docker 映像。
当取消工作流程时,GitHub 根据文档杀死 docker 容器。
有没有办法拦截容器的“kill”,以便我可以在终止容器之前在容器中运行一些拆卸命令?
至少可以通过使用自定义入口点脚本定义自定义操作来实现。
虽然您无法在默认容器化操作中使用
--entrypoint
(如此处所述),但您可以创建自己的操作并定义一个入口点脚本,您可以在其中捕获发送到容器的 SIGINT GitHub:
对于需要取消的步骤,运行器机器将 SIGINT/Ctrl-C 发送到步骤的入口进程(用于容器操作的 docker)。如果进程在 7500 毫秒内没有退出,运行程序将向进程发送 SIGTERM/Ctrl-Break,然后等待 2500 毫秒让进程退出。如果进程仍在运行,则运行程序会杀死进程树。
这是我的存储库中的自定义操作的示例。我有以下结构:
repository
├── .github
│ ├── actions
│ │ └── test-teri
│ │ ├── Dockerfile
│ │ ├── action.yml
│ │ └── entrypoint.sh
│ └── workflows
│ └── cd_workflow.yml
Dockerfile 只是 GH 操作文档的副本。
FROM alpine:3.10
COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
在entrypoint.sh中我有这个过程的要点:
#!/bin/sh -l
trap cleanup SIGINT
cleanup() {
sleep 2
echo "Cleanup successful."
exit
}
while true
do
echo "Testing..."
sleep 1
done
我将
SIGINT
信号捕获在入口点内,并在发生这种情况时调用清理函数。该脚本通常只是无限地打印 Testing...
到输出,但您可以定义入口点,使其根据工作流程中的 run:
指令或您想要的方式调用其他内容。我不会详细说明这一点。
记得给入口点脚本赋予执行权限,否则无法运行。
最后是我的 action.yml,您可以在其中定义用于运行此操作的 Dockerfile。
# action.yml
name: 'Hello World'
description: 'Test sigint'
runs:
using: 'docker'
image: 'Dockerfile'
然后,您只需在工作流程中使用此自定义操作即可。
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...
Testing...
Testing...
Testing...
Testing...
Testing...
Testing...
Cleanup successful.
Error: The operation was canceled.
您注意到清理功能已被执行。但请注意,运行的时间限制是 7500 毫秒,因此它需要在这段时间内成功。我不知道您是否可以在 GH 操作中以任何方式自定义该时间。