Compare commits

...

3 Commits

Author SHA1 Message Date
github-actions[bot]
2a98f257a8 Update CHANGELOG.md 2026-02-16 16:14:19 +00:00
CanbiZ (MickLesk)
896714e06f core/vm's: ensure script state is sent on script exit (#11991)
* Ensure API update is sent on script exit

Add exit-time telemetry handling across scripts to avoid orphaned "installing" records. Introduce local exit_code capture in api_exit_script and cleanup handlers and, when POST_TO_API_DONE is true but POST_UPDATE_DONE is not, post a final status (marking failures on non-zero exit codes, or marking done/failed in VM cleanups based on exit code). Changes touch misc/build.func, misc/vm-core.func and various vm/*-vm.sh cleanup functions to reliably send post_update_to_api on normal or early exits.

* Update api.func

* fix(telemetry): add missing exit codes to explain_exit_code()

- Add curl error codes: 4, 5, 8, 23, 25, 30, 56, 78
- Add code 10: Docker/privileged mode required (used in ~15 scripts)
- Add code 75: Temporary failure (retry later)
- Add BSD sysexits.h codes: 64-77
- Sync error_handler.func fallback with canonical api.func
2026-02-16 17:14:00 +01:00
community-scripts-pr-app[bot]
96389a02cb chore: update github-versions.json (#11996)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-16 12:14:25 +00:00
20 changed files with 212 additions and 26 deletions

View File

@@ -422,6 +422,7 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
- #### 🔧 Refactor - #### 🔧 Refactor
- core/vm's: ensure script state is sent on script exit [@MickLesk](https://github.com/MickLesk) ([#11991](https://github.com/community-scripts/ProxmoxVE/pull/11991))
- Vaultwarden: export VW_VERSION as version number [@MickLesk](https://github.com/MickLesk) ([#11966](https://github.com/community-scripts/ProxmoxVE/pull/11966)) - Vaultwarden: export VW_VERSION as version number [@MickLesk](https://github.com/MickLesk) ([#11966](https://github.com/community-scripts/ProxmoxVE/pull/11966))
- Zabbix: Improve zabbix-agent service detection [@MickLesk](https://github.com/MickLesk) ([#11968](https://github.com/community-scripts/ProxmoxVE/pull/11968)) - Zabbix: Improve zabbix-agent service detection [@MickLesk](https://github.com/MickLesk) ([#11968](https://github.com/community-scripts/ProxmoxVE/pull/11968))

View File

@@ -1,5 +1,5 @@
{ {
"generated": "2026-02-16T06:25:10Z", "generated": "2026-02-16T12:14:16Z",
"versions": [ "versions": [
{ {
"slug": "2fauth", "slug": "2fauth",
@@ -557,9 +557,9 @@
{ {
"slug": "immich-public-proxy", "slug": "immich-public-proxy",
"repo": "alangrainger/immich-public-proxy", "repo": "alangrainger/immich-public-proxy",
"version": "v1.15.1", "version": "v1.15.2",
"pinned": false, "pinned": false,
"date": "2026-01-26T08:04:27Z" "date": "2026-02-16T08:54:59Z"
}, },
{ {
"slug": "inspircd", "slug": "inspircd",
@@ -585,9 +585,9 @@
{ {
"slug": "jackett", "slug": "jackett",
"repo": "Jackett/Jackett", "repo": "Jackett/Jackett",
"version": "v0.24.1124", "version": "v0.24.1127",
"pinned": false, "pinned": false,
"date": "2026-02-15T05:54:22Z" "date": "2026-02-16T08:43:41Z"
}, },
{ {
"slug": "jellystat", "slug": "jellystat",
@@ -729,6 +729,13 @@
"pinned": false, "pinned": false,
"date": "2025-11-16T22:40:18Z" "date": "2025-11-16T22:40:18Z"
}, },
{
"slug": "linkding",
"repo": "sissbruecker/linkding",
"version": "v1.45.0",
"pinned": false,
"date": "2026-01-06T20:31:04Z"
},
{ {
"slug": "linkstack", "slug": "linkstack",
"repo": "linkstackorg/linkstack", "repo": "linkstackorg/linkstack",
@@ -963,9 +970,9 @@
{ {
"slug": "ots", "slug": "ots",
"repo": "Luzifer/ots", "repo": "Luzifer/ots",
"version": "v1.21.0", "version": "v1.21.1",
"pinned": false, "pinned": false,
"date": "2026-01-19T23:21:29Z" "date": "2026-02-16T12:12:23Z"
}, },
{ {
"slug": "outline", "slug": "outline",
@@ -1012,9 +1019,9 @@
{ {
"slug": "paperless-gpt", "slug": "paperless-gpt",
"repo": "icereed/paperless-gpt", "repo": "icereed/paperless-gpt",
"version": "v0.24.0", "version": "v0.25.0",
"pinned": false, "pinned": false,
"date": "2026-01-14T21:28:09Z" "date": "2026-02-16T08:31:48Z"
}, },
{ {
"slug": "paperless-ngx", "slug": "paperless-ngx",
@@ -1268,6 +1275,13 @@
"pinned": false, "pinned": false,
"date": "2025-03-28T13:00:23Z" "date": "2025-03-28T13:00:23Z"
}, },
{
"slug": "romm",
"repo": "RetroAchievements/RALibretro",
"version": "1.8.2",
"pinned": false,
"date": "2026-01-23T17:03:31Z"
},
{ {
"slug": "rustdeskserver", "slug": "rustdeskserver",
"repo": "rustdesk/rustdesk-server", "repo": "rustdesk/rustdesk-server",
@@ -1320,9 +1334,9 @@
{ {
"slug": "semaphore", "slug": "semaphore",
"repo": "semaphoreui/semaphore", "repo": "semaphoreui/semaphore",
"version": "v2.17.0", "version": "v2.17.2",
"pinned": false, "pinned": false,
"date": "2026-02-13T21:08:30Z" "date": "2026-02-16T10:27:40Z"
}, },
{ {
"slug": "shelfmark", "slug": "shelfmark",
@@ -1726,9 +1740,9 @@
{ {
"slug": "zitadel", "slug": "zitadel",
"repo": "zitadel/zitadel", "repo": "zitadel/zitadel",
"version": "v4.10.1", "version": "v4.11.0",
"pinned": false, "pinned": false,
"date": "2026-01-30T06:52:53Z" "date": "2026-02-16T09:48:38Z"
}, },
{ {
"slug": "zoraxy", "slug": "zoraxy",

View File

@@ -135,19 +135,44 @@ explain_exit_code() {
# --- Generic / Shell --- # --- Generic / Shell ---
1) echo "General error / Operation not permitted" ;; 1) echo "General error / Operation not permitted" ;;
2) echo "Misuse of shell builtins (e.g. syntax error)" ;; 2) echo "Misuse of shell builtins (e.g. syntax error)" ;;
10) echo "Docker / privileged mode required (unsupported environment)" ;;
# --- curl / wget errors (commonly seen in downloads) --- # --- curl / wget errors (commonly seen in downloads) ---
4) echo "curl: Feature not supported or protocol error" ;;
5) echo "curl: Could not resolve proxy" ;;
6) echo "curl: DNS resolution failed (could not resolve host)" ;; 6) echo "curl: DNS resolution failed (could not resolve host)" ;;
7) echo "curl: Failed to connect (network unreachable / host down)" ;; 7) echo "curl: Failed to connect (network unreachable / host down)" ;;
8) echo "curl: FTP server reply error" ;;
22) echo "curl: HTTP error returned (404, 429, 500+)" ;; 22) echo "curl: HTTP error returned (404, 429, 500+)" ;;
23) echo "curl: Write error (disk full or permissions)" ;;
25) echo "curl: Upload failed" ;;
28) echo "curl: Operation timeout (network slow or server not responding)" ;; 28) echo "curl: Operation timeout (network slow or server not responding)" ;;
30) echo "curl: FTP port command failed" ;;
35) echo "curl: SSL/TLS handshake failed (certificate error)" ;; 35) echo "curl: SSL/TLS handshake failed (certificate error)" ;;
56) echo "curl: Receive error (connection reset by peer)" ;;
75) echo "Temporary failure (retry later)" ;;
78) echo "curl: Remote file not found (404 on FTP/file)" ;;
# --- Package manager / APT / DPKG --- # --- Package manager / APT / DPKG ---
100) echo "APT: Package manager error (broken packages / dependency problems)" ;; 100) echo "APT: Package manager error (broken packages / dependency problems)" ;;
101) echo "APT: Configuration error (bad sources.list, malformed config)" ;; 101) echo "APT: Configuration error (bad sources.list, malformed config)" ;;
102) echo "APT: Lock held by another process (dpkg/apt still running)" ;; 102) echo "APT: Lock held by another process (dpkg/apt still running)" ;;
# --- BSD sysexits.h (64-78) ---
64) echo "Usage error (wrong arguments)" ;;
65) echo "Data format error (bad input data)" ;;
66) echo "Input file not found (cannot open input)" ;;
67) echo "User not found (addressee unknown)" ;;
68) echo "Host not found (hostname unknown)" ;;
69) echo "Service unavailable" ;;
70) echo "Internal software error" ;;
71) echo "System error (OS-level failure)" ;;
72) echo "Critical OS file missing" ;;
73) echo "Cannot create output file" ;;
74) echo "I/O error" ;;
76) echo "Remote protocol error" ;;
77) echo "Permission denied" ;;
# --- Common shell/system errors --- # --- Common shell/system errors ---
124) echo "Command timed out (timeout command)" ;; 124) echo "Command timed out (timeout command)" ;;
126) echo "Command invoked cannot execute (permission problem?)" ;; 126) echo "Command invoked cannot execute (permission problem?)" ;;
@@ -624,6 +649,8 @@ EOF
curl -fsS -m "${TELEMETRY_TIMEOUT}" -X POST "${TELEMETRY_URL}" \ curl -fsS -m "${TELEMETRY_TIMEOUT}" -X POST "${TELEMETRY_URL}" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d "$JSON_PAYLOAD" &>/dev/null || true -d "$JSON_PAYLOAD" &>/dev/null || true
POST_TO_API_DONE=true
} }
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------

View File

@@ -5253,14 +5253,20 @@ ensure_log_on_host() {
# - Exit trap handler for reporting to API telemetry # - Exit trap handler for reporting to API telemetry
# - Captures exit code and reports to PocketBase using centralized error descriptions # - Captures exit code and reports to PocketBase using centralized error descriptions
# - Uses explain_exit_code() from api.func for consistent error messages # - Uses explain_exit_code() from api.func for consistent error messages
# - Posts failure status with exit code to API (error description resolved automatically) # - For non-zero exit codes: posts "failed" status
# - Only executes on non-zero exit codes # - For zero exit codes where post_update_to_api was never called:
# catches orphaned "installing" records (e.g., script exited cleanly
# but description() was never reached)
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
api_exit_script() { api_exit_script() {
exit_code=$? local exit_code=$?
if [ $exit_code -ne 0 ]; then if [ $exit_code -ne 0 ]; then
ensure_log_on_host ensure_log_on_host
post_update_to_api "failed" "$exit_code" post_update_to_api "failed" "$exit_code"
elif [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
# Script exited with 0 but never sent a completion status
# This catches edge cases like early returns after post_to_api()
post_update_to_api "failed" "1"
fi fi
} }

View File

@@ -37,11 +37,34 @@ if ! declare -f explain_exit_code &>/dev/null; then
case "$code" in case "$code" in
1) echo "General error / Operation not permitted" ;; 1) echo "General error / Operation not permitted" ;;
2) echo "Misuse of shell builtins (e.g. syntax error)" ;; 2) echo "Misuse of shell builtins (e.g. syntax error)" ;;
10) echo "Docker / privileged mode required (unsupported environment)" ;;
4) echo "curl: Feature not supported or protocol error" ;;
5) echo "curl: Could not resolve proxy" ;;
6) echo "curl: DNS resolution failed (could not resolve host)" ;; 6) echo "curl: DNS resolution failed (could not resolve host)" ;;
7) echo "curl: Failed to connect (network unreachable / host down)" ;; 7) echo "curl: Failed to connect (network unreachable / host down)" ;;
8) echo "curl: FTP server reply error" ;;
22) echo "curl: HTTP error returned (404, 429, 500+)" ;; 22) echo "curl: HTTP error returned (404, 429, 500+)" ;;
23) echo "curl: Write error (disk full or permissions)" ;;
25) echo "curl: Upload failed" ;;
28) echo "curl: Operation timeout (network slow or server not responding)" ;; 28) echo "curl: Operation timeout (network slow or server not responding)" ;;
30) echo "curl: FTP port command failed" ;;
35) echo "curl: SSL/TLS handshake failed (certificate error)" ;; 35) echo "curl: SSL/TLS handshake failed (certificate error)" ;;
56) echo "curl: Receive error (connection reset by peer)" ;;
75) echo "Temporary failure (retry later)" ;;
78) echo "curl: Remote file not found (404 on FTP/file)" ;;
64) echo "Usage error (wrong arguments)" ;;
65) echo "Data format error (bad input data)" ;;
66) echo "Input file not found (cannot open input)" ;;
67) echo "User not found (addressee unknown)" ;;
68) echo "Host not found (hostname unknown)" ;;
69) echo "Service unavailable" ;;
70) echo "Internal software error" ;;
71) echo "System error (OS-level failure)" ;;
72) echo "Critical OS file missing" ;;
73) echo "Cannot create output file" ;;
74) echo "I/O error" ;;
76) echo "Remote protocol error" ;;
77) echo "Permission denied" ;;
100) echo "APT: Package manager error (broken packages / dependency problems)" ;; 100) echo "APT: Package manager error (broken packages / dependency problems)" ;;
101) echo "APT: Configuration error (bad sources.list, malformed config)" ;; 101) echo "APT: Configuration error (bad sources.list, malformed config)" ;;
102) echo "APT: Lock held by another process (dpkg/apt still running)" ;; 102) echo "APT: Lock held by another process (dpkg/apt still running)" ;;

View File

@@ -529,9 +529,21 @@ cleanup_vmid() {
} }
cleanup() { cleanup() {
local exit_code=$?
if [[ "$(dirs -p | wc -l)" -gt 1 ]]; then if [[ "$(dirs -p | wc -l)" -gt 1 ]]; then
popd >/dev/null || true popd >/dev/null || true
fi fi
# Report final telemetry status if post_to_api_vm was called but no update was sent
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
if declare -f post_update_to_api >/dev/null 2>&1; then
if [[ $exit_code -ne 0 ]]; then
post_update_to_api "failed" "$exit_code"
else
# Exited cleanly but description()/success was never called — shouldn't happen
post_update_to_api "failed" "1"
fi
fi
fi
} }
check_root() { check_root() {

View File

@@ -100,8 +100,15 @@ function cleanup_vmid() {
} }
function cleanup() { function cleanup() {
local exit_code=$?
popd >/dev/null popd >/dev/null
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
if [[ $exit_code -eq 0 ]]; then
post_update_to_api "done" "none" post_update_to_api "done" "none"
else
post_update_to_api "failed" "$exit_code"
fi
fi
rm -rf $TEMP_DIR rm -rf $TEMP_DIR
} }

View File

@@ -100,8 +100,15 @@ function cleanup_vmid() {
} }
function cleanup() { function cleanup() {
local exit_code=$?
popd >/dev/null popd >/dev/null
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
if [[ $exit_code -eq 0 ]]; then
post_update_to_api "done" "none" post_update_to_api "done" "none"
else
post_update_to_api "failed" "$exit_code"
fi
fi
rm -rf $TEMP_DIR rm -rf $TEMP_DIR
} }

View File

@@ -100,8 +100,15 @@ function cleanup_vmid() {
} }
function cleanup() { function cleanup() {
local exit_code=$?
popd >/dev/null popd >/dev/null
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
if [[ $exit_code -eq 0 ]]; then
post_update_to_api "done" "none" post_update_to_api "done" "none"
else
post_update_to_api "failed" "$exit_code"
fi
fi
rm -rf $TEMP_DIR rm -rf $TEMP_DIR
} }

View File

@@ -104,8 +104,16 @@ function cleanup_vmid() {
} }
function cleanup() { function cleanup() {
local exit_code=$?
popd >/dev/null popd >/dev/null
# Only send telemetry if post_to_api_vm was called (installing status was sent)
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
if [[ $exit_code -eq 0 ]]; then
post_update_to_api "done" "none" post_update_to_api "done" "none"
else
post_update_to_api "failed" "$exit_code"
fi
fi
rm -rf $TEMP_DIR rm -rf $TEMP_DIR
} }

View File

@@ -101,8 +101,15 @@ function cleanup_vmid() {
} }
function cleanup() { function cleanup() {
local exit_code=$?
popd >/dev/null popd >/dev/null
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
if [[ $exit_code -eq 0 ]]; then
post_update_to_api "done" "none" post_update_to_api "done" "none"
else
post_update_to_api "failed" "$exit_code"
fi
fi
rm -rf $TEMP_DIR rm -rf $TEMP_DIR
} }

View File

@@ -100,8 +100,15 @@ function cleanup_vmid() {
} }
function cleanup() { function cleanup() {
local exit_code=$?
popd >/dev/null popd >/dev/null
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
if [[ $exit_code -eq 0 ]]; then
post_update_to_api "done" "none" post_update_to_api "done" "none"
else
post_update_to_api "failed" "$exit_code"
fi
fi
rm -rf $TEMP_DIR rm -rf $TEMP_DIR
} }

View File

@@ -105,7 +105,15 @@ function cleanup_vmid() {
} }
function cleanup() { function cleanup() {
local exit_code=$?
popd >/dev/null popd >/dev/null
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
if [[ $exit_code -eq 0 ]]; then
post_update_to_api "done" "none"
else
post_update_to_api "failed" "$exit_code"
fi
fi
rm -rf $TEMP_DIR rm -rf $TEMP_DIR
} }

View File

@@ -79,8 +79,15 @@ function cleanup_vmid() {
} }
function cleanup() { function cleanup() {
local exit_code=$?
popd >/dev/null popd >/dev/null
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
if [[ $exit_code -eq 0 ]]; then
post_update_to_api "done" "none" post_update_to_api "done" "none"
else
post_update_to_api "failed" "$exit_code"
fi
fi
rm -rf $TEMP_DIR rm -rf $TEMP_DIR
} }

View File

@@ -101,8 +101,15 @@ function cleanup_vmid() {
} }
function cleanup() { function cleanup() {
local exit_code=$?
popd >/dev/null popd >/dev/null
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
if [[ $exit_code -eq 0 ]]; then
post_update_to_api "done" "none" post_update_to_api "done" "none"
else
post_update_to_api "failed" "$exit_code"
fi
fi
rm -rf $TEMP_DIR rm -rf $TEMP_DIR
} }

View File

@@ -109,8 +109,15 @@ function cleanup_vmid() {
} }
function cleanup() { function cleanup() {
local exit_code=$?
popd >/dev/null popd >/dev/null
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
if [[ $exit_code -eq 0 ]]; then
post_update_to_api "done" "none" post_update_to_api "done" "none"
else
post_update_to_api "failed" "$exit_code"
fi
fi
rm -rf $TEMP_DIR rm -rf $TEMP_DIR
} }

View File

@@ -97,7 +97,15 @@ function cleanup_vmid() {
} }
function cleanup() { function cleanup() {
local exit_code=$?
popd >/dev/null popd >/dev/null
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
if [[ $exit_code -eq 0 ]]; then
post_update_to_api "done" "none"
else
post_update_to_api "failed" "$exit_code"
fi
fi
rm -rf $TEMP_DIR rm -rf $TEMP_DIR
} }

View File

@@ -100,7 +100,15 @@ function cleanup_vmid() {
} }
function cleanup() { function cleanup() {
local exit_code=$?
popd >/dev/null popd >/dev/null
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
if [[ $exit_code -eq 0 ]]; then
post_update_to_api "done" "none"
else
post_update_to_api "failed" "$exit_code"
fi
fi
rm -rf $TEMP_DIR rm -rf $TEMP_DIR
} }

View File

@@ -99,7 +99,15 @@ function cleanup_vmid() {
} }
function cleanup() { function cleanup() {
local exit_code=$?
popd >/dev/null popd >/dev/null
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
if [[ $exit_code -eq 0 ]]; then
post_update_to_api "done" "none"
else
post_update_to_api "failed" "$exit_code"
fi
fi
rm -rf $TEMP_DIR rm -rf $TEMP_DIR
} }

View File

@@ -99,8 +99,15 @@ function cleanup_vmid() {
} }
function cleanup() { function cleanup() {
local exit_code=$?
popd >/dev/null popd >/dev/null
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
if [[ $exit_code -eq 0 ]]; then
post_update_to_api "done" "none" post_update_to_api "done" "none"
else
post_update_to_api "failed" "$exit_code"
fi
fi
rm -rf $TEMP_DIR rm -rf $TEMP_DIR
} }