summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-06-12 15:05:26 +0300
committerPaul Buetow <paul@buetow.org>2026-06-12 15:05:26 +0300
commit6aa19aa81090898c942f44677867b1abcdb06589 (patch)
tree8525c98a90fbf1676145d3314909f77a69ec93c2
parentc2ff4241715fe80ef33b6a6e6e0d2fa523ba0089 (diff)
Capture action and template setup failures for bm0
-rwxr-xr-xbin/shuriken30
-rw-r--r--src/lib/action.source.sh18
-rw-r--r--src/lib/template.source.sh12
-rwxr-xr-xtests/cli.sh145
4 files changed, 185 insertions, 20 deletions
diff --git a/bin/shuriken b/bin/shuriken
index b9df7c1..58fa2ac 100755
--- a/bin/shuriken
+++ b/bin/shuriken
@@ -749,12 +749,14 @@ source_template_file() {
return "$status"
fi
- {
- serialize_template_render_context "$render_vars_name"
+ if {
+ serialize_template_render_context "$render_vars_name" \
+ &&
printf 'unset BASH_ENV\n'
- } > "$context_file"
- status=$?
- if (( status != 0 )); then
+ } > "$context_file"; then
+ status=0
+ else
+ status=$?
rm -f "$context_file"
return "$status"
fi
@@ -3129,6 +3131,14 @@ run_simple_action() {
esac
}
+run_action_body() {
+ if [[ "$-" == *e* ]]; then
+ "$@"
+ else
+ ( "$@" )
+ fi
+}
+
load_configured_action() {
local -r rc_file="$1"; shift
local -i status=0
@@ -3221,7 +3231,7 @@ run_configured_action() {
return "$status"
fi
- generate_staged
+ run_action_body generate_staged
status=$?
if (( status != 0 )); then
return "$status"
@@ -3234,7 +3244,7 @@ run_configured_action() {
return "$status"
fi
- refresh_splash
+ run_action_body refresh_splash
status=$?
if (( status != 0 )); then
return "$status"
@@ -3247,7 +3257,7 @@ run_configured_action() {
return "$status"
fi
- sync_dist
+ run_action_body sync_dist
status=$?
if (( status != 0 )); then
return "$status"
@@ -3260,7 +3270,7 @@ run_configured_action() {
return "$status"
fi
- dry_run
+ run_action_body dry_run
status=$?
if (( status != 0 )); then
return "$status"
@@ -3273,7 +3283,7 @@ run_configured_action() {
return "$status"
fi
- print_config
+ run_action_body print_config
status=$?
if (( status != 0 )); then
return "$status"
diff --git a/src/lib/action.source.sh b/src/lib/action.source.sh
index 165cb2b..aba24a8 100644
--- a/src/lib/action.source.sh
+++ b/src/lib/action.source.sh
@@ -23,6 +23,14 @@ run_simple_action() {
esac
}
+run_action_body() {
+ if [[ "$-" == *e* ]]; then
+ "$@"
+ else
+ ( "$@" )
+ fi
+}
+
load_configured_action() {
local -r rc_file="$1"; shift
local -i status=0
@@ -115,7 +123,7 @@ run_configured_action() {
return "$status"
fi
- generate_staged
+ run_action_body generate_staged
status=$?
if (( status != 0 )); then
return "$status"
@@ -128,7 +136,7 @@ run_configured_action() {
return "$status"
fi
- refresh_splash
+ run_action_body refresh_splash
status=$?
if (( status != 0 )); then
return "$status"
@@ -141,7 +149,7 @@ run_configured_action() {
return "$status"
fi
- sync_dist
+ run_action_body sync_dist
status=$?
if (( status != 0 )); then
return "$status"
@@ -154,7 +162,7 @@ run_configured_action() {
return "$status"
fi
- dry_run
+ run_action_body dry_run
status=$?
if (( status != 0 )); then
return "$status"
@@ -167,7 +175,7 @@ run_configured_action() {
return "$status"
fi
- print_config
+ run_action_body print_config
status=$?
if (( status != 0 )); then
return "$status"
diff --git a/src/lib/template.source.sh b/src/lib/template.source.sh
index e29458a..58cdfa8 100644
--- a/src/lib/template.source.sh
+++ b/src/lib/template.source.sh
@@ -304,12 +304,14 @@ source_template_file() {
return "$status"
fi
- {
- serialize_template_render_context "$render_vars_name"
+ if {
+ serialize_template_render_context "$render_vars_name" \
+ &&
printf 'unset BASH_ENV\n'
- } > "$context_file"
- status=$?
- if (( status != 0 )); then
+ } > "$context_file"; then
+ status=0
+ else
+ status=$?
rm -f "$context_file"
return "$status"
fi
diff --git a/tests/cli.sh b/tests/cli.sh
index 25f003f..0f6470f 100755
--- a/tests/cli.sh
+++ b/tests/cli.sh
@@ -2129,6 +2129,79 @@ BASH
test::teardown
}
+test_generate_real_failure_returns_with_errexit_disabled() {
+ local config_file
+ local fake_bin
+ local output
+ local status_file
+ local -i status=0
+
+ test::setup
+ fake_bin="$TEST_TMPDIR/bin"
+ config_file="$TEST_TMPDIR/shuriken.conf"
+ status_file="$TEST_TMPDIR/generate-status"
+ test::install_failing_imagemagick "$fake_bin"
+ mkdir -p "$TEST_TMPDIR/incoming" "$TEST_TMPDIR/dist"
+ printf 'fake image\n' > "$TEST_TMPDIR/incoming/01.jpg"
+ printf 'old dist\n' > "$TEST_TMPDIR/dist/index.html"
+ test::write_album_config \
+ "$config_file" "$TEST_TMPDIR/incoming" "$TEST_TMPDIR/dist" \
+ 'Failing set+e generate album' 40
+
+ set +e
+ output=$(
+ bash -euo pipefail -s \
+ "$TEST_SHURIKEN" \
+ "$config_file" \
+ "$fake_bin" \
+ "$status_file" \
+ 2>&1 \
+ <<'BASH'
+shuriken="$1"; shift
+config_file="$1"; shift
+fake_bin="$1"; shift
+status_file="$1"; shift
+
+# shellcheck source=/dev/null
+source <(sed '$d' "$shuriken")
+
+PATH="$fake_bin:$PATH"
+SHURIKEN_CLI_ACTION=--generate
+SHURIKEN_CLI_CONFIG_FILE="$config_file"
+SHURIKEN_CLI_HAS_CONFIG_OVERRIDES=no
+SHURIKEN_CLI_OVERRIDES=()
+SHURIKEN_CLI_SYNC_DESTINATIONS=()
+SHURIKEN_FORCE_GENERATE=no
+
+set +e
+run_configured_action
+generate_status=$?
+printf '%s\n' "$generate_status" > "$status_file"
+exit 0
+BASH
+ )
+ status=$?
+ set -e
+
+ if (( status != 0 )); then
+ printf 'FAIL: expected child shell to capture generate status\n' >&2
+ printf '%s\n' "$output" >&2
+ exit 1
+ fi
+
+ test::assert_file_exists "$status_file"
+ if [ "$(<"$status_file")" = 0 ]; then
+ printf 'FAIL: expected generated status to be nonzero\n' >&2
+ printf '%s\n' "$output" >&2
+ exit 1
+ fi
+ test::assert_contains 'simulated ImageMagick failure' "$output"
+ test "$(<"$TEST_TMPDIR/dist/index.html")" = 'old dist'
+ test::assert_path_absent "$TEST_TMPDIR/dist/photos/01.jpg"
+ test::assert_no_staging_dirs "$TEST_TMPDIR"
+ test::teardown
+}
+
test_generate_preflight_accepts_empty_height() {
local config_file
local fake_bin
@@ -3487,6 +3560,72 @@ BASH
test::teardown
}
+test_template_setup_failure_removes_context_file_with_errexit() {
+ local context_file
+ local fake_bin
+ local output
+ local template_file
+ local -i status=0
+
+ test::setup
+ fake_bin="$TEST_TMPDIR/bin"
+ context_file="$TEST_TMPDIR/template-context"
+ template_file="$TEST_TMPDIR/template.tmpl"
+ mkdir -p "$fake_bin" "$TEST_TMPDIR/dist"
+ {
+ printf '#!/usr/bin/env bash\n'
+ # shellcheck disable=SC2016
+ printf 'printf %%s\\\\n \"$SHURIKEN_FAKE_CONTEXT_FILE\"\n'
+ } > "$fake_bin/mktemp"
+ chmod 0755 "$fake_bin/mktemp"
+ printf 'printf rendered\n' > "$template_file"
+
+ set +e
+ output=$(
+ bash -euo pipefail -s \
+ "$TEST_SHURIKEN" \
+ "$fake_bin" \
+ "$template_file" \
+ "$TEST_TMPDIR/dist/out.html" \
+ "$context_file" \
+ 2>&1 \
+ <<'BASH'
+shuriken="$1"; shift
+fake_bin="$1"; shift
+template_file="$1"; shift
+output_file="$1"; shift
+context_file="$1"; shift
+
+# shellcheck source=/dev/null
+source <(sed '$d' "$shuriken")
+
+PATH="$fake_bin:$PATH"
+SHURIKEN_FAKE_CONTEXT_FILE="$context_file"
+export SHURIKEN_FAKE_CONTEXT_FILE
+
+serialize_template_render_context() {
+ printf 'partial_context=yes\n'
+ return 42
+}
+
+# shellcheck disable=SC2034
+declare -A render_vars=()
+source_template_file "$template_file" "$output_file" render_vars
+BASH
+ )
+ status=$?
+ set -e
+
+ if (( status == 0 )); then
+ printf 'FAIL: expected template setup to fail\n' >&2
+ printf '%s\n' "$output" >&2
+ exit 1
+ fi
+
+ test::assert_path_absent "$context_file"
+ test::teardown
+}
+
test_generate_swap_failure_restores_dist() {
local config_file
local fake_bin
@@ -4307,6 +4446,9 @@ main() {
'--generate action runs with errexit active' \
test_generate_action_runs_with_errexit_active
test::run_case \
+ '--generate real failure returns with errexit disabled' \
+ test_generate_real_failure_returns_with_errexit_disabled
+ test::run_case \
'--generate preflight accepts empty HEIGHT' \
test_generate_preflight_accepts_empty_height
test::run_case \
@@ -4397,6 +4539,9 @@ main() {
'template failure removes context file with errexit' \
test_template_failure_removes_context_file_with_errexit
test::run_case \
+ 'template setup failure removes context file with errexit' \
+ test_template_setup_failure_removes_context_file_with_errexit
+ test::run_case \
'--generate swap failure restores final dist' \
test_generate_swap_failure_restores_dist
test::run_case \