Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/verify-split-files.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ on:
- "tests/failed-command-output.sh"
- "tests/exit-code-hints.sh"
- "tests/forge-release-json.sh"
- "tests/install-cleanup.sh"
- ".github/workflows/verify-split-files.yml"
push:
branches: [main]
Expand All @@ -61,6 +62,7 @@ on:
- "tests/failed-command-output.sh"
- "tests/exit-code-hints.sh"
- "tests/forge-release-json.sh"
- "tests/install-cleanup.sh"
- ".github/workflows/verify-split-files.yml"
workflow_dispatch:

Expand Down Expand Up @@ -121,6 +123,9 @@ jobs:
- name: Forge release lookup tests
run: bash tests/forge-release-json.sh

- name: Install cleanup and uv trap tests
run: bash tests/install-cleanup.sh

- name: Prefetch lists cover every engine file
run: |
set -euo pipefail
Expand Down
7 changes: 5 additions & 2 deletions core/core.func
Original file line number Diff line number Diff line change
Expand Up @@ -2307,7 +2307,8 @@ cs_testing_state() {
# cleanup_lxc()
#
# - Cleans package manager and language caches (safe for installs AND updates)
# - Supports Alpine (apk), Debian/Ubuntu (apt), Python, Node.js, Go, Rust, Ruby, PHP
# - Supports Alpine (apk), Debian/Ubuntu (apt), other distros through install.func's
# pkg_clean, and Python, Node.js, Go, Rust, Ruby, PHP caches
# - Uses fallback error handling to prevent cleanup failures from breaking installs
# ------------------------------------------------------------------------------
cleanup_lxc() {
Expand All @@ -2321,10 +2322,12 @@ cleanup_lxc() {
# problem worth reporting.
$STD apk cache clean 2>/dev/null || true
rm -rf /var/cache/apk/*
else
elif command -v apt-get &>/dev/null; then
$STD apt -y autoremove 2>/dev/null || msg_warn "apt autoremove failed (non-critical)"
$STD apt -y autoclean 2>/dev/null || msg_warn "apt autoclean failed (non-critical)"
$STD apt -y clean 2>/dev/null || msg_warn "apt clean failed (non-critical)"
elif declare -f pkg_clean >/dev/null 2>&1; then
pkg_clean 2>/dev/null || msg_warn "Package cache cleanup failed (non-critical)"
fi

find /tmp /var/tmp -type f -name 'tmp*' -delete 2>/dev/null || true
Expand Down
4 changes: 4 additions & 0 deletions core/error_handler.func
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,10 @@ on_exit() {

# Here, because most ct scripts exit inside update_script.
declare -f apt_conffile_report >/dev/null 2>&1 && apt_conffile_report
if [[ $exit_code -eq 0 && "${_CS_UPDATE_CLEANUP:-}" == "1" ]] && declare -f cleanup_lxc >/dev/null 2>&1; then
_CS_UPDATE_CLEANUP=0
cleanup_lxc || true
fi

if _is_container_context; then
if [[ $exit_code -ne 0 ]]; then
Expand Down
4 changes: 2 additions & 2 deletions lib/runtime.func
Original file line number Diff line number Diff line change
Expand Up @@ -2720,8 +2720,8 @@ setup_uv() {
local UVX_BIN="/usr/local/bin/uvx"
local TMP_DIR=$(mktemp -d)

# trap for TMP Cleanup
trap "rm -rf '$TMP_DIR'" EXIT
# RETURN, not EXIT: an EXIT trap here replaced catch_errors' on_exit for the rest of the script
trap 'rm -rf "$TMP_DIR"; trap - RETURN' RETURN

# Architecture Detection
local ARCH=$(uname -m)
Expand Down
10 changes: 0 additions & 10 deletions lxc/install.func
Original file line number Diff line number Diff line change
Expand Up @@ -1883,13 +1883,3 @@ os_info() {
echo "Pkg Manager: $PKG_MANAGER"
echo "Init System: $INIT_SYSTEM"
}

# ------------------------------------------------------------------------------
# cleanup_lxc()
#
# Overrides core.func version to support all OS types (not just Alpine/Debian)
# Cleans package caches and removes unnecessary packages after installation
# ------------------------------------------------------------------------------
cleanup_lxc() {
pkg_clean
}
71 changes: 71 additions & 0 deletions tests/install-cleanup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#!/usr/bin/env bash
set -euo pipefail

CORE_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
eval "$(awk '/^setup_uv\(\) \{/,/^}/' "$CORE_DIR/lib/runtime.func")"
eval "$(awk '/^on_exit\(\) \{/,/^}/' "$CORE_DIR/core/error_handler.func")"
eval "$(awk '/^cleanup_lxc\(\) \{/,/^}/' "$CORE_DIR/core/core.func")"

TEST_DIR="$(mktemp -d)"
trap 'rm -rf -- "$TEST_DIR"' EXIT
passed=0 failed=0

check() {
if [[ "$3" == "$2" ]]; then
echo "PASS $1"
passed=$((passed + 1))
else
echo "FAIL $1: expected <$2>, got <$3>" >&2
failed=$((failed + 1))
fi
}

# shellcheck disable=SC2034 # read by the eval'd helpers
STD=""
msg_info() { :; }
msg_ok() { :; }
msg_error() { :; }
msg_warn() { :; }
ensure_dependencies() { :; }
curl_with_retry() { return 1; }
_is_container_context() { return 0; }
_container_write_failure() { :; }

# setup_uv returning early (here: a failed download) must leave the caller's EXIT trap alone
mktemp() { command mktemp "$@" | tee "$TEST_DIR/uv-tmp"; }
result=$(
trap ':' EXIT
UV_VERSION=0.0.1 setup_uv >/dev/null 2>&1 || true
trap -p EXIT
)
unset -f mktemp
check "setup_uv keeps the caller's EXIT trap" "trap -- ':' EXIT" "$result"
check "setup_uv removes its temp dir" "gone" "$([[ -d "$(cat "$TEST_DIR/uv-tmp")" ]] && echo left || echo gone)"

run_exit() {
rm -f "$TEST_DIR/cleaned"
(
cleanup_lxc() { touch "$TEST_DIR/cleaned"; }
_CS_UPDATE_CLEANUP="$1"
trap on_exit EXIT
exit "$2"
) || true
[[ -e "$TEST_DIR/cleaned" ]] && echo ran || echo skipped
}
check "update exits inside update_script: cleanup runs" "ran" "$(run_exit 1 0)"
check "failed update: no cleanup" "skipped" "$(run_exit 1 1)"
check "not an update: no cleanup" "skipped" "$(run_exit "" 0)"

# An empty PATH stands in for a distro without apt-get, and keeps cleanup_lxc's find away from /tmp
mkdir "$TEST_DIR/bin"
result=$(
PATH="$TEST_DIR/bin"
is_alpine() { return 1; }
pkg_clean() { echo pkg_clean; }
cleanup_lxc 2>/dev/null
)
check "no apt-get: cleanup_lxc cleans through pkg_clean" "pkg_clean" "$result"
check "install.func does not shadow core.func's cleanup_lxc" "" "$(grep -n '^cleanup_lxc()' "$CORE_DIR/lxc/install.func" || true)"

printf '%s passed, %s failed\n' "$passed" "$failed"
((failed == 0))
6 changes: 3 additions & 3 deletions ui/menu.func
Original file line number Diff line number Diff line change
Expand Up @@ -1115,8 +1115,8 @@ check_breaking_change_guard() {

# The update path, shared by the three branches of start() that reach it.
# exit, not return: returning continues into the ct script's host-only tail.
# Most ct scripts exit inside update_script, so the three calls after it are
# unreachable for them.
# Most ct scripts exit inside update_script, so the two calls after it are
# unreachable for them; the cleanup therefore runs from on_exit.
_cs_run_update() {
ensure_profile_loaded
ensure_recorded_toolchains
Expand All @@ -1126,10 +1126,10 @@ _cs_run_update() {
check_container_os_guard || exit 0
check_breaking_change_guard || exit 0
apt_conffile_guard
_CS_UPDATE_CLEANUP=1
update_script
run_addon_updates
update_motd_ip
cleanup_lxc
exit 0
}

Expand Down
Loading