diff --git a/ci/build-dev-image.sh b/ci/build-dev-image.sh index 32eca5a..199be31 100644 --- a/ci/build-dev-image.sh +++ b/ci/build-dev-image.sh @@ -30,6 +30,49 @@ fi exit 2 } +active_command_pid="" +cancel_active_command() { + local pid="${active_command_pid:-}" + [[ -n "$pid" ]] || return 0 + + kill -TERM -- "-$pid" 2>/dev/null || true + kill -TERM "$pid" 2>/dev/null || true + for _ in {1..10}; do + kill -0 -- "-$pid" 2>/dev/null || break + sleep 1 + done + kill -KILL -- "-$pid" 2>/dev/null || true + kill -KILL "$pid" 2>/dev/null || true + wait "$pid" 2>/dev/null || true + active_command_pid="" +} + +handle_cancel() { + trap - TERM INT HUP + cancel_active_command + exit 143 +} + +trap handle_cancel TERM INT HUP + +run_bounded() { + local duration="$1" status=0 + shift + + # setsid gives the command its own process group so a cancel signal can + # terminate Buildah and its children even when the local backend only signals + # the shell process. timeout is the fallback if cancellation is lost entirely. + setsid timeout --foreground --signal=TERM --kill-after=30s "$duration" "$@" <&0 & + active_command_pid=$! + if wait "$active_command_pid"; then + status=0 + else + status=$? + fi + active_command_pid="" + return "$status" +} + root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" # 版本:v<下一个补丁版本>-dev.<自最近 tag 的提交数>-<提交前 7 位>(见 ci/version.sh);写进工作区的 Directory.Build.props,镜像标签、构建信息、签名清单都用它 source "$root/ci/version.sh" @@ -48,7 +91,7 @@ if [[ "$component" == backend ]]; then ZOT_IMAGE_REPOSITORY="$repository" \ IMAGE_TAGS="latest,$image_version" \ IMAGE_PUBLISH=true \ - bash "$root/ci/release-linux.sh" "$arch" backend + run_bounded 30m bash "$root/ci/release-linux.sh" "$arch" backend exit 0 fi @@ -71,7 +114,7 @@ commit_epoch="$(git -C "$root" show -s --format=%ct "$CI_COMMIT_SHA")" built_at="$(date -u -d "@$commit_epoch" +%Y-%m-%dT%H:%M:%SZ)" python3 "$root/ci/stage-node-image.py" "$component" "$context" -buildah bud --layers --network host --tls-verify=true --arch "$arch" \ +run_bounded 30m buildah bud --layers --network host --tls-verify=true --arch "$arch" \ --volume "$nuget_cache:/root/.nuget/packages:rw" \ --build-arg "APP_VERSION=$image_version" \ --build-arg "NODE_RID=$node_rid" \ @@ -81,7 +124,7 @@ buildah bud --layers --network host --tls-verify=true --arch "$arch" \ logged_in=false for attempt in 1 2 3 4; do - if buildah login --tls-verify=true --username "$ZOT_USERNAME" --password-stdin "$registry" <<< "$ZOT_SECRET" >/dev/null; then + if run_bounded 2m buildah login --tls-verify=true --username "$ZOT_USERNAME" --password-stdin "$registry" <<< "$ZOT_SECRET" >/dev/null; then logged_in=true break fi @@ -95,7 +138,7 @@ done for tag in "$image_version-$arch"; do pushed=false for attempt in 1 2 3; do - if buildah push --tls-verify=true --digestfile "$work/$component.digest" "$local_image" "docker://$repository:$tag"; then + if run_bounded 10m buildah push --tls-verify=true --digestfile "$work/$component.digest" "$local_image" "docker://$repository:$tag"; then pushed=true break fi