Skip to content

Commit 51b25a3

Browse files
committed
refactor(ci): share dmg parser and canonicalize workspace matching
1 parent e2b16ad commit 51b25a3

1 file changed

Lines changed: 89 additions & 63 deletions

File tree

.github/workflows/build-desktop-tauri.yml

Lines changed: 89 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -285,9 +285,12 @@ jobs:
285285
detach_attempts=3
286286
detach_sleep_seconds=2
287287
rw_dmg_image_prefix='/src-tauri/target/'
288-
rw_dmg_image_suffix_regex='/bundle/macos/rw\\..*\\.dmg$'
288+
rw_dmg_image_suffix_regex='/bundle/macos/rw\..*\.dmg$'
289+
allow_global_helper_cleanup="${ASTRBOT_DESKTOP_MACOS_ALLOW_GLOBAL_HELPER_KILL:-0}"
289290
log_file=""
290291
workspace_root="${GITHUB_WORKSPACE:-$(pwd)}"
292+
workspace_root_raw="${workspace_root%/}"
293+
workspace_root="${workspace_root_raw}"
291294
workspace_root="${workspace_root%/}"
292295
293296
cleanup_log_file() {
@@ -313,23 +316,32 @@ jobs:
313316
return 1
314317
}
315318
316-
cleanup_stale_dmg_state() {
317-
local dmg_mounts
318-
dmg_mounts="$(mount | awk '$3 ~ /^\/Volumes\/dmg\./ { print $3 }' || true)"
319-
if [ -n "${dmg_mounts}" ]; then
320-
while IFS= read -r mount_point; do
321-
[ -z "${mount_point}" ] && continue
322-
echo "Detaching stale mount ${mount_point}"
323-
detach_target "${mount_point}" || true
324-
done <<< "${dmg_mounts}"
325-
fi
319+
canonicalize_path() {
320+
local raw_path="$1"
321+
python3 -c 'import os,sys; print(os.path.realpath(sys.argv[1]))' "${raw_path}"
322+
}
326323
327-
local workspace_disks
328-
workspace_disks="$(hdiutil info 2>/dev/null | awk \
329-
-v root="${workspace_root}" \
330-
-v image_prefix="${rw_dmg_image_prefix}" \
331-
-v image_suffix_re="${rw_dmg_image_suffix_regex}" '
332-
BEGIN { image = ""; dev = "" }
324+
is_workspace_rw_dmg_image() {
325+
local image="$1"
326+
local normalized_image
327+
normalized_image="$(canonicalize_path "${image}")"
328+
local candidate
329+
for candidate in "${image}" "${normalized_image}"; do
330+
if [[ "${candidate}" == "${workspace_root}${rw_dmg_image_prefix}"* ]] &&
331+
[[ "${candidate}" =~ ${rw_dmg_image_suffix_regex} ]]; then
332+
return 0
333+
fi
334+
if [[ "${candidate}" == "${workspace_root_raw}${rw_dmg_image_prefix}"* ]] &&
335+
[[ "${candidate}" =~ ${rw_dmg_image_suffix_regex} ]]; then
336+
return 0
337+
fi
338+
done
339+
return 1
340+
}
341+
342+
collect_dmg_records() {
343+
hdiutil info 2>/dev/null | awk '
344+
BEGIN { image = ""; dev = ""; pid = "" }
333345
/^image-path[[:space:]]*:/ {
334346
line = $0
335347
sub(/^image-path[[:space:]]*:[[:space:]]*/, "", line)
@@ -340,24 +352,70 @@ jobs:
340352
dev = $1
341353
next
342354
}
355+
/^process ID[[:space:]]*:/ {
356+
line = $0
357+
sub(/^process ID[[:space:]]*:[[:space:]]*/, "", line)
358+
pid = line
359+
next
360+
}
343361
/^=+/ {
344-
if (index(image, root image_prefix) == 1 &&
345-
image ~ image_suffix_re &&
346-
dev != "") {
347-
print dev
362+
if (image != "") {
363+
print image "\t" dev "\t" pid
348364
}
349365
image = ""
350366
dev = ""
367+
pid = ""
351368
next
352369
}
353370
END {
354-
if (index(image, root image_prefix) == 1 &&
355-
image ~ image_suffix_re &&
356-
dev != "") {
357-
print dev
371+
if (image != "") {
372+
print image "\t" dev "\t" pid
358373
}
359374
}
360-
' | sort -u)"
375+
'
376+
}
377+
378+
terminate_pid_soft_then_hard() {
379+
local pid="$1"
380+
kill -TERM "${pid}" 2>/dev/null || return 0
381+
sleep 1
382+
if kill -0 "${pid}" 2>/dev/null; then
383+
kill -KILL "${pid}" 2>/dev/null || true
384+
fi
385+
}
386+
387+
cleanup_stale_dmg_state() {
388+
local dmg_mounts
389+
dmg_mounts="$(mount | awk '$3 ~ /^\/Volumes\/dmg\./ { print $3 }' || true)"
390+
if [ -n "${dmg_mounts}" ]; then
391+
while IFS= read -r mount_point; do
392+
[ -z "${mount_point}" ] && continue
393+
echo "Detaching stale mount ${mount_point}"
394+
detach_target "${mount_point}" || true
395+
done <<< "${dmg_mounts}"
396+
fi
397+
398+
local dmg_records
399+
dmg_records="$(collect_dmg_records)"
400+
401+
local workspace_disks
402+
workspace_disks=""
403+
local workspace_helper_pids
404+
workspace_helper_pids=""
405+
while IFS=$'\t' read -r image disk pid; do
406+
[ -z "${image:-}" ] && continue
407+
if ! is_workspace_rw_dmg_image "${image}"; then
408+
continue
409+
fi
410+
if [[ "${disk}" =~ ^/dev/disk[0-9]+$ ]]; then
411+
workspace_disks+="${disk}"$'\n'
412+
fi
413+
if [[ "${pid}" =~ ^[0-9]+$ ]]; then
414+
workspace_helper_pids+="${pid}"$'\n'
415+
fi
416+
done <<< "${dmg_records}"
417+
workspace_disks="$(printf '%s\n' "${workspace_disks}" | awk 'NF' | sort -u)"
418+
workspace_helper_pids="$(printf '%s\n' "${workspace_helper_pids}" | awk 'NF' | sort -u)"
361419
362420
if [ -n "${workspace_disks}" ]; then
363421
while IFS= read -r disk; do
@@ -369,55 +427,23 @@ jobs:
369427
370428
# Prefer process IDs linked to this workspace's RW DMG images.
371429
local helper_pids
372-
helper_pids="$(hdiutil info 2>/dev/null | awk \
373-
-v root="${workspace_root}" \
374-
-v image_prefix="${rw_dmg_image_prefix}" \
375-
-v image_suffix_re="${rw_dmg_image_suffix_regex}" '
376-
BEGIN { image = ""; pid = "" }
377-
/^image-path[[:space:]]*:/ {
378-
line = $0
379-
sub(/^image-path[[:space:]]*:[[:space:]]*/, "", line)
380-
image = line
381-
next
382-
}
383-
/^process ID[[:space:]]*:/ {
384-
line = $0
385-
sub(/^process ID[[:space:]]*:[[:space:]]*/, "", line)
386-
pid = line
387-
next
388-
}
389-
/^=+/ {
390-
if (index(image, root image_prefix) == 1 &&
391-
image ~ image_suffix_re &&
392-
pid ~ /^[0-9]+$/) {
393-
print pid
394-
}
395-
image = ""
396-
pid = ""
397-
next
398-
}
399-
END {
400-
if (index(image, root image_prefix) == 1 &&
401-
image ~ image_suffix_re &&
402-
pid ~ /^[0-9]+$/) {
403-
print pid
404-
}
405-
}
406-
' | sort -u)"
430+
helper_pids="${workspace_helper_pids}"
407431
408432
# Fallback: exact process-name match only, avoid broad -f substring patterns.
409-
if [ -z "${helper_pids}" ]; then
433+
if [ -z "${helper_pids}" ] && [ "${allow_global_helper_cleanup}" = "1" ]; then
410434
helper_pids="$(
411435
pgrep -x diskimages-helper || true
412436
pgrep -x diskimages-help || true
413437
)"
438+
elif [ -z "${helper_pids}" ]; then
439+
echo "Skip global disk image helper cleanup (set ASTRBOT_DESKTOP_MACOS_ALLOW_GLOBAL_HELPER_KILL=1 to enable)." >&2
414440
fi
415441
helper_pids="$(printf '%s\n' "${helper_pids}" | awk 'NF' | sort -u)"
416442
if [ -n "${helper_pids}" ]; then
417443
while IFS= read -r pid; do
418444
[ -z "${pid}" ] && continue
419445
echo "Killing stale disk image helper pid=${pid}"
420-
kill "${pid}" || true
446+
terminate_pid_soft_then_hard "${pid}"
421447
done <<< "${helper_pids}"
422448
fi
423449
}

0 commit comments

Comments
 (0)