From cc6b013b23b66bf2c81f057934ad30ea3cf76650 Mon Sep 17 00:00:00 2001 From: LucaLin <78164141+LucaLin233@users.noreply.github.com> Date: Tue, 8 Sep 2026 08:47:21 +0800 Subject: [PATCH 01/21] chore(ci): inventory pinned ShellCheck warnings --- .github/workflows/shellcheck-inventory.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .github/workflows/shellcheck-inventory.yml diff --git a/.github/workflows/shellcheck-inventory.yml b/.github/workflows/shellcheck-inventory.yml new file mode 100644 index 0000000..b32c153 --- /dev/null +++ b/.github/workflows/shellcheck-inventory.yml @@ -0,0 +1,17 @@ +name: ShellCheck inventory +on: + pull_request: +permissions: + contents: read +jobs: + inventory: + runs-on: ubuntu-24.04 + timeout-minutes: 15 + steps: + - uses: actions/checkout@v7 + with: + persist-credentials: false + - run: | + curl -fsSL https://github.com/koalaman/shellcheck/releases/download/v0.10.0/shellcheck-v0.10.0.linux.x86_64.tar.xz -o "$RUNNER_TEMP/sc.tar.xz" + tar -xJf "$RUNNER_TEMP/sc.tar.xz" -C "$RUNNER_TEMP" + git ls-files -z -- '*.sh' | xargs -0 -r "$RUNNER_TEMP/shellcheck-v0.10.0/shellcheck" -x --severity=warning -- From c66b111740a371df4c5d5e13c043beffd4bde03a Mon Sep 17 00:00:00 2001 From: LucaLin <78164141+LucaLin233@users.noreply.github.com> Date: Tue, 8 Sep 2026 00:57:41 +0000 Subject: [PATCH 02/21] chore(ci): gate production warnings and retain test error checks --- .github/workflows/shell-tests.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/shell-tests.yml b/.github/workflows/shell-tests.yml index ea5eccc..5801221 100644 --- a/.github/workflows/shell-tests.yml +++ b/.github/workflows/shell-tests.yml @@ -55,7 +55,14 @@ jobs: run: find . -type f -name '*.sh' -print0 | xargs -0 -n1 bash -n - name: Run ShellCheck - run: git ls-files -z -- '*.sh' | xargs -0 -r shellcheck -x --severity=error -- + shell: bash + run: | + # All tracked Bash scripts outside tests are production by default. + # Check both groups even when production lint fails. + status=0 + git ls-files -z -- *.sh :!:tests/** | xargs -0 -r shellcheck -x --severity=warning -- || status=1 + git ls-files -z -- tests/**/*.sh | xargs -0 -r shellcheck -x --severity=error -- || status=1 + exit "$status" - name: Run tests env: From f5428a66d68e1c7c57e7c80afc2d8ddd9808d5bc Mon Sep 17 00:00:00 2001 From: LucaLin <78164141+LucaLin233@users.noreply.github.com> Date: Tue, 8 Sep 2026 00:57:56 +0000 Subject: [PATCH 03/21] chore(ci): remove completed temporary warning inventory --- .github/workflows/shellcheck-inventory.yml | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 .github/workflows/shellcheck-inventory.yml diff --git a/.github/workflows/shellcheck-inventory.yml b/.github/workflows/shellcheck-inventory.yml deleted file mode 100644 index b32c153..0000000 --- a/.github/workflows/shellcheck-inventory.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: ShellCheck inventory -on: - pull_request: -permissions: - contents: read -jobs: - inventory: - runs-on: ubuntu-24.04 - timeout-minutes: 15 - steps: - - uses: actions/checkout@v7 - with: - persist-credentials: false - - run: | - curl -fsSL https://github.com/koalaman/shellcheck/releases/download/v0.10.0/shellcheck-v0.10.0.linux.x86_64.tar.xz -o "$RUNNER_TEMP/sc.tar.xz" - tar -xJf "$RUNNER_TEMP/sc.tar.xz" -C "$RUNNER_TEMP" - git ls-files -z -- '*.sh' | xargs -0 -r "$RUNNER_TEMP/shellcheck-v0.10.0/shellcheck" -x --severity=warning -- From d08036c5b08edb9049363e8602f685e61a6c75c5 Mon Sep 17 00:00:00 2001 From: LucaLin <78164141+LucaLin233@users.noreply.github.com> Date: Tue, 8 Sep 2026 00:58:30 +0000 Subject: [PATCH 04/21] fix(ci): quote recursive Git pathspecs --- .github/workflows/shell-tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/shell-tests.yml b/.github/workflows/shell-tests.yml index 5801221..a949d38 100644 --- a/.github/workflows/shell-tests.yml +++ b/.github/workflows/shell-tests.yml @@ -60,8 +60,8 @@ jobs: # All tracked Bash scripts outside tests are production by default. # Check both groups even when production lint fails. status=0 - git ls-files -z -- *.sh :!:tests/** | xargs -0 -r shellcheck -x --severity=warning -- || status=1 - git ls-files -z -- tests/**/*.sh | xargs -0 -r shellcheck -x --severity=error -- || status=1 + git ls-files -z -- "*.sh" ":!:tests/**" | xargs -0 -r shellcheck -x --severity=warning -- || status=1 + git ls-files -z -- "tests/*.sh" | xargs -0 -r shellcheck -x --severity=error -- || status=1 exit "$status" - name: Run tests From 6c98290570d70da22e5866385db9a3c23c156a31 Mon Sep 17 00:00:00 2001 From: LucaLin <78164141+LucaLin233@users.noreply.github.com> Date: Tue, 8 Sep 2026 00:58:46 +0000 Subject: [PATCH 05/21] chore(test): remove file-wide unused-variable suppression --- tests/test-push.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test-push.sh b/tests/test-push.sh index b433c16..d8e186b 100644 --- a/tests/test-push.sh +++ b/tests/test-push.sh @@ -1,5 +1,4 @@ #!/usr/bin/env bash -# shellcheck disable=SC2034 # Test globals are consumed by sourced tools/push.sh functions. set -euo pipefail ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) From 63adfcca9ec4c161617f38feecc2011b1b46cac8 Mon Sep 17 00:00:00 2001 From: LucaLin <78164141+LucaLin233@users.noreply.github.com> Date: Tue, 8 Sep 2026 01:12:12 +0000 Subject: [PATCH 06/21] chore(test): remove redundant warning suppressions from error-gated fixtures --- tests/test-push-worker-registration.sh | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/tests/test-push-worker-registration.sh b/tests/test-push-worker-registration.sh index db007b5..d7d26f4 100755 --- a/tests/test-push-worker-registration.sh +++ b/tests/test-push-worker-registration.sh @@ -89,12 +89,9 @@ setup_fixture() { CURRENT_FIXTURE_ROOT=$root mkdir -m 0700 "$root" "$root/runtime" "$root/capture" TMPDIR="$root/runtime"; initialize_runtime - # shellcheck disable=SC2034 MAX_PARALLEL=2 - # shellcheck disable=SC2034 MAX_RETRIES=1 BATCH_WORKER_FAILED=false - # shellcheck disable=SC2034 BATCH_WORKER_ERROR=false } assert_no_registration_residue() { @@ -182,7 +179,6 @@ CHILD leader_start=$(wait_test_process_start "$leader"); read_process_record "$leader" WORKER_TRANSFER_PID=$leader; WORKER_TRANSFER_START=$leader_start; WORKER_TRANSFER_PGID=$PROC_PGID; WORKER_TRANSFER_SID=$PROC_SID publish_worker_session_state active; state_file=$WORKER_SESSION_STATE_FILE - # shellcheck disable=SC2034 # Consumed by sourced push cleanup state machine. MANAGED_SESSION_CLEANUP_TICKS=300 rc=0; terminate_worker_transfer || rc=$? (( rc != 0 )) || fail "deadline failure unexpectedly succeeded" @@ -258,7 +254,6 @@ run_with_watchdog root-cause 20 root_cause_regression_case run_ready_failure_case() ( kind="$1"; root="$TEST_DIR/ready-$kind"; setup_fixture "$root" - # shellcheck disable=SC2034 WORKER_REGISTRATION_TIMEOUT_TICKS=10 push_to_server() { : > "$root/capture/transfer"; return 0; } case "$kind" in @@ -348,9 +343,7 @@ prune_identity_failure_case repeated root="$TEST_DIR/prune-cleanup-failure"; setup_fixture "$root" sleep 300 & worker=$!; read_process_record "$worker"; start=$PROC_START ACTIVE_WORKERS[$worker]=$start - # shellcheck disable=SC2034 ACTIVE_WORKER_STATE_FILES[$worker]="$TEMP_DIR/worker-session.$worker.state" - # shellcheck disable=SC2034 ACTIVE_WORKER_STATE_STARTS[$worker]=$start eval "$(declare -f process_identity_matches | sed '1s/process_identity_matches/original_process_identity_matches/')" eval "$(declare -f read_process_record_for_session_scan | sed '1s/read_process_record_for_session_scan/original_read_process_record_for_session_scan/')" @@ -373,9 +366,7 @@ prune_identity_failure_case repeated root="$TEST_DIR/prune-exited"; setup_fixture "$root" sleep 0.1 & worker=$!; read_process_record "$worker"; start=$PROC_START ACTIVE_WORKERS[$worker]=$start - # shellcheck disable=SC2034 ACTIVE_WORKER_STATE_FILES[$worker]="$TEMP_DIR/worker-session.$worker.state" - # shellcheck disable=SC2034 ACTIVE_WORKER_STATE_STARTS[$worker]=$start sleep 0.2; prune_active_workers assert_eq 0 "${#ACTIVE_WORKERS[@]}" "exited worker is normally reaped" @@ -541,7 +532,6 @@ pass "failed managed-session reap remains bounded for 20 deterministic runs" TEMP_DIR=$(dirname "$state_file") ACTIVE_WORKERS=(); ACTIVE_WORKER_STATE_FILES=(); ACTIVE_WORKER_STATE_STARTS=() BATCH_WORKER_FAILED=false - # shellcheck disable=SC2034 # Consumed by sourced worker accounting. BATCH_WORKER_ERROR=false MAX_PARALLEL=1 ACTIVE_WORKERS[$worker]=$worker_start @@ -577,7 +567,6 @@ pass "failed managed-session reap remains bounded for 20 deterministic runs" ( trap - EXIT HUP INT TERM leader=424242; leader_start=777777; wait_called=false; after_wait=false - # shellcheck disable=SC2034 # Test double fills caller arrays through namerefs. collect_owned_session_records() { local -n pids_ref="$2" starts_ref="$3" ppids_ref="$4" pgids_ref="$5" states_ref="$6" pids_ref=(); starts_ref=(); ppids_ref=(); pgids_ref=(); states_ref=() @@ -680,13 +669,11 @@ run_preserved_cleanup_retry_case() ( local run="$1" root runtime runtime_dev runtime_inode credential leader leader_start leader_pgid leader_sid state_file local owner watchdog rc=0 metadata="" state_status=0 local -a session_pids=() - # shellcheck disable=SC2034 # Filled through collect_owned_session_records namerefs. local -A session_starts=() session_ppids=() session_pgids=() session_states=() root="$TEST_DIR/runtime-evidence-retry-$run"; setup_fixture "$root" runtime=$TEMP_DIR; runtime_dev=$TEMP_DIR_DEV; runtime_inode=$TEMP_DIR_INODE credential="$runtime/private-key" printf 'fixture-credential-do-not-print\n' > "$credential"; chmod 0600 "$credential" - # shellcheck disable=SC2034 # Consumed by sourced runtime cleanup. RUNTIME_KEY_FILE=$credential setsid bash -c 'trap "" HUP INT TERM; kill -STOP "$BASHPID"; while :; do :; done' & leader=$! @@ -912,7 +899,6 @@ run_runtime_retention_signal_case() ( local signal_name="$1" expected="$2" root leader="" leader_start="" leader_pgid="" leader_sid="" target="" target_pid="" target_start="" local runtime runtime_dev runtime_inode state_file credential watchdog="" rc=0 line key value state_status=0 reap_status=0 local -a session_pids=() - # shellcheck disable=SC2034 # Filled through collect_owned_session_records namerefs. local -A session_starts=() session_ppids=() session_pgids=() session_states=() cleanup_runtime_retention_signal_fixture() { if [[ -n "$target" ]]; then kill -KILL "$target" 2>/dev/null || true; wait "$target" 2>/dev/null || true; fi @@ -1135,7 +1121,6 @@ done run_parallel_fallback_iteration() ( run="$1"; root="$TEST_DIR/session-parallel-$run"; setup_fixture "$root" - # shellcheck disable=SC2034 # consumed by sourced run_server_batch MAX_PARALLEL=2 push_to_server() { local server="$1" lock_fd @@ -1143,13 +1128,9 @@ run_parallel_fallback_iteration() ( printf '%s\n' "$server" >> "$root/capture/calls"; : > "$root/capture/ready.$server" flock -u "$lock_fd"; exec {lock_fd}>&- while [[ ! -e "$root/capture/release" ]]; do sleep 0.01; done - # shellcheck disable=SC2034 # consumed by sourced state publisher WORKER_TRANSFER_PID=$BASHPID - # shellcheck disable=SC2034 # consumed by sourced state publisher WORKER_TRANSFER_START=11 - # shellcheck disable=SC2034 # consumed by sourced state publisher WORKER_TRANSFER_PGID=$BASHPID - # shellcheck disable=SC2034 # consumed by sourced state publisher WORKER_TRANSFER_SID=$BASHPID publish_worker_session_state cleanup_failed return "$MANAGED_CLEANUP_FAILURE_STATUS" @@ -1336,7 +1317,6 @@ run_live_cleanup_failure_signal_case() ( } trap cleanup_live_failure_fixture EXIT local -a session_pids=() - # shellcheck disable=SC2034 # Filled by collect_owned_session_records namerefs. local -A session_starts=() session_ppids=() session_pgids=() session_states=() root="$TEST_DIR/live-cleanup-failure-$signal_name"; CURRENT_FIXTURE_ROOT=$root write_active_grace_fixture "$root" @@ -1422,7 +1402,6 @@ run_state_publication_signal_case() ( local state="$1" phase="$2" signal_name="$3" expected="$4" mode root main_pid="" main_start="" worker_pid="" worker_start="" leader_pid="" leader_start="" managed_sid="" local watchdog="" watchdog_start="" unrelated="" unrelated_start="" rc=0 line key value marker state_file hook_stage local -a session_pids=() - # shellcheck disable=SC2034 # Filled by collect_owned_session_records namerefs. local -A session_starts=() session_ppids=() session_pgids=() session_states=() cleanup_publication_fixture() { [[ -z "$worker_pid" || -z "$worker_start" ]] || { test_process_identity_exists "$worker_pid" "$worker_start" && kill -KILL "$worker_pid" 2>/dev/null || true; } From 3cb353a806953ed6f9e75f2d6d50217a8d81d0f0 Mon Sep 17 00:00:00 2001 From: LucaLin <78164141+LucaLin233@users.noreply.github.com> Date: Tue, 8 Sep 2026 01:12:35 +0000 Subject: [PATCH 07/21] chore(lint): use explicit bounded retry counters --- modules/system-customize.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/system-customize.sh b/modules/system-customize.sh index 31d4a39..71884ed 100644 --- a/modules/system-customize.sh +++ b/modules/system-customize.sh @@ -3000,7 +3000,7 @@ xanmod_allocate_temp_directory() { [[ -z "$XANMOD_ALLOCATION_CANDIDATE" && -z "$XANMOD_ALLOCATION_STATE" ]] || return 1 printf -v "$path_variable" '%s' "" printf -v "$building_variable" '%s' false - for attempt in {1..64}; do + for (( attempt=1; attempt<=64; attempt++ )); do token=$(xanmod_random_token) || return 1 owner_token=$(xanmod_random_token) || return 1 candidate="$parent/$prefix.$token" @@ -3068,7 +3068,7 @@ xanmod_allocate_temp_file() { [[ -d "$parent" && ! -L "$parent" ]] || return 1 [[ -z "$XANMOD_ALLOCATION_CANDIDATE" && -z "$XANMOD_ALLOCATION_STATE" ]] || return 1 printf -v "$path_variable" '%s' "" - for attempt in {1..64}; do + for (( attempt=1; attempt<=64; attempt++ )); do token=$(xanmod_random_token) || return 1 owner_token=$(xanmod_random_token) || return 1 candidate="$parent/$prefix.$token$suffix" From 47b637cf46e4e8b34ad966daa5eb2052955da1eb Mon Sep 17 00:00:00 2001 From: LucaLin <78164141+LucaLin233@users.noreply.github.com> Date: Tue, 8 Sep 2026 01:12:55 +0000 Subject: [PATCH 08/21] chore(lint): mirror bounded retry counter in standalone tool --- tools/xanmod-install.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/xanmod-install.sh b/tools/xanmod-install.sh index 9c7839e..5620a2e 100755 --- a/tools/xanmod-install.sh +++ b/tools/xanmod-install.sh @@ -899,7 +899,7 @@ xanmod_allocate_temp_directory() { [[ -z "$XANMOD_ALLOCATION_CANDIDATE" && -z "$XANMOD_ALLOCATION_STATE" ]] || return 1 printf -v "$path_variable" '%s' "" printf -v "$building_variable" '%s' false - for attempt in {1..64}; do + for (( attempt=1; attempt<=64; attempt++ )); do token=$(xanmod_random_token) || return 1 owner_token=$(xanmod_random_token) || return 1 candidate="$parent/$prefix.$token" @@ -967,7 +967,7 @@ xanmod_allocate_temp_file() { [[ -d "$parent" && ! -L "$parent" ]] || return 1 [[ -z "$XANMOD_ALLOCATION_CANDIDATE" && -z "$XANMOD_ALLOCATION_STATE" ]] || return 1 printf -v "$path_variable" '%s' "" - for attempt in {1..64}; do + for (( attempt=1; attempt<=64; attempt++ )); do token=$(xanmod_random_token) || return 1 owner_token=$(xanmod_random_token) || return 1 candidate="$parent/$prefix.$token$suffix" From 088c19042337d551be3cde5888c327078c74bff9 Mon Sep 17 00:00:00 2001 From: LucaLin <78164141+LucaLin233@users.noreply.github.com> Date: Tue, 8 Sep 2026 01:13:43 +0000 Subject: [PATCH 09/21] docs(ci): document warning coverage and exception boundaries --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1b38090..369f6e7 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,9 @@ 生产宿主机(包括 Netcup)仅执行差异检查及改动脚本的 `bash -n`,不运行全量 ShellCheck 或完整测试集; 分析和测试交由 CI:PR 按完整差异及依赖映射选择套件,README/许可证修改无需业务测试; 公共设施或未知依赖改动回退全量,main 推送仍执行全量。两个必需 Job 始终运行,输出选择和跳过记录。 -ShellCheck 与语法检查仍覆盖全部脚本;文档修改无需本地全套测试,但仍须通过必需 CI。 +Ubuntu 使用固定 ShellCheck v0.10.0:所有受 Git 跟踪、位于 tests/ 之外的 .sh 文件执行 warning 门槛,tests/ 内的 .sh 文件执行 error 门槛;新目录中的生产 .sh 文件自动纳入,不维护生产文件白名单。Zsh 配置 p10k-config.zsh 不交给 Bash ShellCheck。两组 lint 都会执行并累计失败,Debian 不重复 lint。 +例外仅允许局部明确的 SC 规则编号和邻近理由;禁止文件级或全局 warning 抑制。测试 warning 不阻断不等于被 disable,禁止用抑制隐藏行为缺陷。CI 工作流改动继续触发全量测试回退;warning 门槛失败时后续 Ubuntu 行为套件不会执行,不能以 Debian 通过代替双环境验收。 +语法检查仍覆盖全部 .sh 脚本;文档修改无需本地全套测试,但仍须通过必需 CI。 本机重测试必须使用原生资源限制及权限隔离;无法隔离或超限时停止,不自动提高额度或转宿主机执行。 ## 快速开始 From 0d4137eb8cfe48ab6d0ad790c0b7d6170249370d Mon Sep 17 00:00:00 2001 From: LucaLin <78164141+LucaLin233@users.noreply.github.com> Date: Tue, 8 Sep 2026 01:31:46 +0000 Subject: [PATCH 10/21] test(ci): verify recursive production and test lint coverage --- tests/test-lint-coverage.sh | 1 + 1 file changed, 1 insertion(+) create mode 100644 tests/test-lint-coverage.sh diff --git a/tests/test-lint-coverage.sh b/tests/test-lint-coverage.sh new file mode 100644 index 0000000..f1f641a --- /dev/null +++ b/tests/test-lint-coverage.sh @@ -0,0 +1 @@ +#!/usr/bin/env bash From 34c48fc71cd8f8155ab73fc25abf1e3cdc79f30d Mon Sep 17 00:00:00 2001 From: LucaLin <78164141+LucaLin233@users.noreply.github.com> Date: Tue, 8 Sep 2026 01:32:13 +0000 Subject: [PATCH 11/21] test(ci): exercise tracked recursive lint pathsets --- tests/test-lint-coverage.sh | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/test-lint-coverage.sh b/tests/test-lint-coverage.sh index f1f641a..28097cb 100644 --- a/tests/test-lint-coverage.sh +++ b/tests/test-lint-coverage.sh @@ -1 +1,22 @@ #!/usr/bin/env bash +set -euo pipefail +# Inert local Git fixture only; never execute production scripts. +unset GH_TOKEN GITHUB_TOKEN SSH_PRIVATE_KEY_B64 +export GIT_CONFIG_NOSYSTEM=1 GIT_CONFIG_GLOBAL=/dev/null +unset GIT_DIR GIT_WORK_TREE GIT_INDEX_FILE GIT_CONFIG_COUNT +root=$(mktemp -d) +trap "rm -rf -- \"$root\"" EXIT +git init -q "$root" +cd "$root" +mkdir -p new/deep tests/nested +touch entry.sh new/deep/production.sh "new/space name.sh" tests/direct.sh tests/nested/deep.sh ignored.zsh +git add . +touch untracked.sh +mapfile -d "" -t production < <(git ls-files -z -- "*.sh" ":!:tests/**") +mapfile -d "" -t tests < <(git ls-files -z -- "tests/*.sh") +[[ ${#production[@]} == 3 && ${#tests[@]} == 2 ]] +[[ ${production[0]} == entry.sh ]] +[[ ${production[1]} == new/deep/production.sh ]] +[[ ${production[2]} == "new/space name.sh" ]] +[[ ${tests[0]} == tests/direct.sh && ${tests[1]} == tests/nested/deep.sh ]] +printf "PASS: recursive tracked production/test lint coverage\n" From 84731a5e409302201424449b2a86b75cae342798 Mon Sep 17 00:00:00 2001 From: LucaLin <78164141+LucaLin233@users.noreply.github.com> Date: Tue, 8 Sep 2026 01:34:05 +0000 Subject: [PATCH 12/21] chore(lint): preserve indirect allocation output state writes --- modules/system-customize.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/system-customize.sh b/modules/system-customize.sh index 71884ed..180a463 100644 --- a/modules/system-customize.sh +++ b/modules/system-customize.sh @@ -1913,7 +1913,7 @@ XANMOD_STAGED_SOURCE="" XANMOD_CANDIDATE_SOURCE="" XANMOD_ARMORED_KEY_TEMP="" XANMOD_ACTIVE_APT_LISTS_DIR="" -XANMOD_ACTIVE_APT_LISTS_BUILDING=false +printf -v XANMOD_ACTIVE_APT_LISTS_BUILDING "%s" false XANMOD_ALLOCATION_CANDIDATE="" XANMOD_ALLOCATION_KIND="" XANMOD_ALLOCATION_OWNER_TOKEN="" @@ -1951,7 +1951,7 @@ XANMOD_BACKUP_SNAPSHOT_BUILDING=false XANMOD_BACKUP_SNAPSHOT_REMOVED=false XANMOD_BACKUP_GROUP_SNAPSHOT_DIR="" XANMOD_BACKUP_STAGE_DIR="" -XANMOD_BACKUP_STAGE_BUILDING=false +printf -v XANMOD_BACKUP_STAGE_BUILDING "%s" false XANMOD_BACKUP_TRANSACTION_ID="" XANMOD_CONFIGURATION_PREVIOUSLY_MANAGED=false XANMOD_BACKUP_SNAPSHOT_PATHS=() @@ -3122,13 +3122,13 @@ xanmod_allocate_temp_file() { cleanup_xanmod_active_apt_lists() { if [[ -z "$XANMOD_ACTIVE_APT_LISTS_DIR" ]]; then - XANMOD_ACTIVE_APT_LISTS_BUILDING=false + printf -v XANMOD_ACTIVE_APT_LISTS_BUILDING "%s" false return 0 fi if [[ ! -e "$XANMOD_ACTIVE_APT_LISTS_DIR" && ! -L "$XANMOD_ACTIVE_APT_LISTS_DIR" ]] || remove_xanmod_temp_directory "$XANMOD_ACTIVE_APT_LISTS_DIR" "临时 APT lists"; then XANMOD_ACTIVE_APT_LISTS_DIR="" - XANMOD_ACTIVE_APT_LISTS_BUILDING=false + printf -v XANMOD_ACTIVE_APT_LISTS_BUILDING "%s" false return 0 fi return 1 @@ -3141,7 +3141,7 @@ xanmod_source_is_usable() { xanmod_allocate_temp_directory XANMOD_ACTIVE_APT_LISTS_DIR \ XANMOD_ACTIVE_APT_LISTS_BUILDING "$temp_parent" xanmod-apt-lists 0755 || return 1 - XANMOD_ACTIVE_APT_LISTS_BUILDING=false + printf -v XANMOD_ACTIVE_APT_LISTS_BUILDING "%s" false if ! install -d -m 0755 "$XANMOD_ACTIVE_APT_LISTS_DIR/partial"; then cleanup_xanmod_active_apt_lists || true return 1 @@ -3957,14 +3957,14 @@ commit_xanmod_backup_group() { cleanup_xanmod_backup_stage() { if [[ -z "$XANMOD_BACKUP_STAGE_DIR" ]]; then - XANMOD_BACKUP_STAGE_BUILDING=false + printf -v XANMOD_BACKUP_STAGE_BUILDING "%s" false return 0 fi if ! remove_xanmod_temp_directory "$XANMOD_BACKUP_STAGE_DIR" "XanMod backup stage"; then return 1 fi XANMOD_BACKUP_STAGE_DIR="" - XANMOD_BACKUP_STAGE_BUILDING=false + printf -v XANMOD_BACKUP_STAGE_BUILDING "%s" false } restore_xanmod_backup_group_snapshot() { @@ -4065,7 +4065,7 @@ prepare_persistent_xanmod_backups() { restore_xanmod_backup_group_snapshot || true return 1 fi - XANMOD_BACKUP_STAGE_BUILDING=false + printf -v XANMOD_BACKUP_STAGE_BUILDING "%s" false if xanmod_configuration_looks_previously_managed; then XANMOD_CONFIGURATION_PREVIOUSLY_MANAGED=true From 7f5b4793433ab47c855821eeaf26af05301507b7 Mon Sep 17 00:00:00 2001 From: LucaLin <78164141+LucaLin233@users.noreply.github.com> Date: Tue, 8 Sep 2026 01:34:19 +0000 Subject: [PATCH 13/21] revert: keep unused-state diagnostics visible pending semantic fix --- modules/system-customize.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/system-customize.sh b/modules/system-customize.sh index 180a463..71884ed 100644 --- a/modules/system-customize.sh +++ b/modules/system-customize.sh @@ -1913,7 +1913,7 @@ XANMOD_STAGED_SOURCE="" XANMOD_CANDIDATE_SOURCE="" XANMOD_ARMORED_KEY_TEMP="" XANMOD_ACTIVE_APT_LISTS_DIR="" -printf -v XANMOD_ACTIVE_APT_LISTS_BUILDING "%s" false +XANMOD_ACTIVE_APT_LISTS_BUILDING=false XANMOD_ALLOCATION_CANDIDATE="" XANMOD_ALLOCATION_KIND="" XANMOD_ALLOCATION_OWNER_TOKEN="" @@ -1951,7 +1951,7 @@ XANMOD_BACKUP_SNAPSHOT_BUILDING=false XANMOD_BACKUP_SNAPSHOT_REMOVED=false XANMOD_BACKUP_GROUP_SNAPSHOT_DIR="" XANMOD_BACKUP_STAGE_DIR="" -printf -v XANMOD_BACKUP_STAGE_BUILDING "%s" false +XANMOD_BACKUP_STAGE_BUILDING=false XANMOD_BACKUP_TRANSACTION_ID="" XANMOD_CONFIGURATION_PREVIOUSLY_MANAGED=false XANMOD_BACKUP_SNAPSHOT_PATHS=() @@ -3122,13 +3122,13 @@ xanmod_allocate_temp_file() { cleanup_xanmod_active_apt_lists() { if [[ -z "$XANMOD_ACTIVE_APT_LISTS_DIR" ]]; then - printf -v XANMOD_ACTIVE_APT_LISTS_BUILDING "%s" false + XANMOD_ACTIVE_APT_LISTS_BUILDING=false return 0 fi if [[ ! -e "$XANMOD_ACTIVE_APT_LISTS_DIR" && ! -L "$XANMOD_ACTIVE_APT_LISTS_DIR" ]] || remove_xanmod_temp_directory "$XANMOD_ACTIVE_APT_LISTS_DIR" "临时 APT lists"; then XANMOD_ACTIVE_APT_LISTS_DIR="" - printf -v XANMOD_ACTIVE_APT_LISTS_BUILDING "%s" false + XANMOD_ACTIVE_APT_LISTS_BUILDING=false return 0 fi return 1 @@ -3141,7 +3141,7 @@ xanmod_source_is_usable() { xanmod_allocate_temp_directory XANMOD_ACTIVE_APT_LISTS_DIR \ XANMOD_ACTIVE_APT_LISTS_BUILDING "$temp_parent" xanmod-apt-lists 0755 || return 1 - printf -v XANMOD_ACTIVE_APT_LISTS_BUILDING "%s" false + XANMOD_ACTIVE_APT_LISTS_BUILDING=false if ! install -d -m 0755 "$XANMOD_ACTIVE_APT_LISTS_DIR/partial"; then cleanup_xanmod_active_apt_lists || true return 1 @@ -3957,14 +3957,14 @@ commit_xanmod_backup_group() { cleanup_xanmod_backup_stage() { if [[ -z "$XANMOD_BACKUP_STAGE_DIR" ]]; then - printf -v XANMOD_BACKUP_STAGE_BUILDING "%s" false + XANMOD_BACKUP_STAGE_BUILDING=false return 0 fi if ! remove_xanmod_temp_directory "$XANMOD_BACKUP_STAGE_DIR" "XanMod backup stage"; then return 1 fi XANMOD_BACKUP_STAGE_DIR="" - printf -v XANMOD_BACKUP_STAGE_BUILDING "%s" false + XANMOD_BACKUP_STAGE_BUILDING=false } restore_xanmod_backup_group_snapshot() { @@ -4065,7 +4065,7 @@ prepare_persistent_xanmod_backups() { restore_xanmod_backup_group_snapshot || true return 1 fi - printf -v XANMOD_BACKUP_STAGE_BUILDING "%s" false + XANMOD_BACKUP_STAGE_BUILDING=false if xanmod_configuration_looks_previously_managed; then XANMOD_CONFIGURATION_PREVIOUSLY_MANAGED=true From f75d2fb32da92819cdaa9c6e7de916c770893d43 Mon Sep 17 00:00:00 2001 From: LucaLin <78164141+LucaLin233@users.noreply.github.com> Date: Tue, 8 Sep 2026 11:06:02 +0000 Subject: [PATCH 14/21] fix(lint): remove write-only allocation flags --- modules/system-customize.sh | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/modules/system-customize.sh b/modules/system-customize.sh index 3b15b93..dc5a670 100644 --- a/modules/system-customize.sh +++ b/modules/system-customize.sh @@ -1913,7 +1913,6 @@ XANMOD_STAGED_SOURCE="" XANMOD_CANDIDATE_SOURCE="" XANMOD_ARMORED_KEY_TEMP="" XANMOD_ACTIVE_APT_LISTS_DIR="" -XANMOD_ACTIVE_APT_LISTS_BUILDING=false XANMOD_ALLOCATION_CANDIDATE="" XANMOD_ALLOCATION_KIND="" XANMOD_ALLOCATION_OWNER_TOKEN="" @@ -1951,7 +1950,6 @@ XANMOD_BACKUP_SNAPSHOT_BUILDING=false XANMOD_BACKUP_SNAPSHOT_REMOVED=false XANMOD_BACKUP_GROUP_SNAPSHOT_DIR="" XANMOD_BACKUP_STAGE_DIR="" -XANMOD_BACKUP_STAGE_BUILDING=false XANMOD_BACKUP_TRANSACTION_ID="" XANMOD_CONFIGURATION_PREVIOUSLY_MANAGED=false XANMOD_BACKUP_SNAPSHOT_PATHS=() @@ -3000,7 +2998,10 @@ xanmod_allocate_temp_directory() { [[ -d "$parent" && ! -L "$parent" ]] || return 1 [[ -z "$XANMOD_ALLOCATION_CANDIDATE" && -z "$XANMOD_ALLOCATION_STATE" ]] || return 1 printf -v "$path_variable" '%s' "" - printf -v "$building_variable" '%s' false + # Callers without a building-state consumer omit this optional output. + if [[ -n "$building_variable" ]]; then + printf -v "$building_variable" "%s" false + fi for (( attempt=1; attempt<=64; attempt++ )); do token=$(xanmod_random_token) || return 1 owner_token=$(xanmod_random_token) || return 1 @@ -3123,13 +3124,11 @@ xanmod_allocate_temp_file() { cleanup_xanmod_active_apt_lists() { if [[ -z "$XANMOD_ACTIVE_APT_LISTS_DIR" ]]; then - XANMOD_ACTIVE_APT_LISTS_BUILDING=false return 0 fi if [[ ! -e "$XANMOD_ACTIVE_APT_LISTS_DIR" && ! -L "$XANMOD_ACTIVE_APT_LISTS_DIR" ]] || remove_xanmod_temp_directory "$XANMOD_ACTIVE_APT_LISTS_DIR" "临时 APT lists"; then XANMOD_ACTIVE_APT_LISTS_DIR="" - XANMOD_ACTIVE_APT_LISTS_BUILDING=false return 0 fi return 1 @@ -3141,8 +3140,7 @@ xanmod_source_is_usable() { local temp_parent="${TMPDIR:-/tmp}" xanmod_allocate_temp_directory XANMOD_ACTIVE_APT_LISTS_DIR \ - XANMOD_ACTIVE_APT_LISTS_BUILDING "$temp_parent" xanmod-apt-lists 0755 || return 1 - XANMOD_ACTIVE_APT_LISTS_BUILDING=false + "" "$temp_parent" xanmod-apt-lists 0755 || return 1 if ! install -d -m 0755 "$XANMOD_ACTIVE_APT_LISTS_DIR/partial"; then cleanup_xanmod_active_apt_lists || true return 1 @@ -3958,14 +3956,12 @@ commit_xanmod_backup_group() { cleanup_xanmod_backup_stage() { if [[ -z "$XANMOD_BACKUP_STAGE_DIR" ]]; then - XANMOD_BACKUP_STAGE_BUILDING=false return 0 fi if ! remove_xanmod_temp_directory "$XANMOD_BACKUP_STAGE_DIR" "XanMod backup stage"; then return 1 fi XANMOD_BACKUP_STAGE_DIR="" - XANMOD_BACKUP_STAGE_BUILDING=false } restore_xanmod_backup_group_snapshot() { @@ -4062,11 +4058,10 @@ prepare_persistent_xanmod_backups() { create_xanmod_backup_group_snapshot || return 1 XANMOD_BACKUP_TRANSACTION_ID=$(basename "$XANMOD_BACKUP_GROUP_SNAPSHOT_DIR") if ! xanmod_allocate_temp_directory XANMOD_BACKUP_STAGE_DIR \ - XANMOD_BACKUP_STAGE_BUILDING "$XANMOD_BACKUP_STATE_DIR" .xanmod-backup-stage 0700; then + "" "$XANMOD_BACKUP_STATE_DIR" .xanmod-backup-stage 0700; then restore_xanmod_backup_group_snapshot || true return 1 fi - XANMOD_BACKUP_STAGE_BUILDING=false if xanmod_configuration_looks_previously_managed; then XANMOD_CONFIGURATION_PREVIOUSLY_MANAGED=true From 86e7f70be2c333b841f3415c13f337e428d0b564 Mon Sep 17 00:00:00 2001 From: LucaLin <78164141+LucaLin233@users.noreply.github.com> Date: Tue, 8 Sep 2026 11:06:17 +0000 Subject: [PATCH 15/21] fix(lint): mirror optional allocation state in standalone tool --- tools/xanmod-install.sh | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tools/xanmod-install.sh b/tools/xanmod-install.sh index 305d425..d5f115f 100755 --- a/tools/xanmod-install.sh +++ b/tools/xanmod-install.sh @@ -66,7 +66,6 @@ XANMOD_STAGED_SOURCE="" XANMOD_CANDIDATE_SOURCE="" XANMOD_ARMORED_KEY_TEMP="" XANMOD_ACTIVE_APT_LISTS_DIR="" -XANMOD_ACTIVE_APT_LISTS_BUILDING=false XANMOD_ALLOCATION_CANDIDATE="" XANMOD_ALLOCATION_KIND="" XANMOD_ALLOCATION_OWNER_TOKEN="" @@ -899,7 +898,10 @@ xanmod_allocate_temp_directory() { [[ -d "$parent" && ! -L "$parent" ]] || return 1 [[ -z "$XANMOD_ALLOCATION_CANDIDATE" && -z "$XANMOD_ALLOCATION_STATE" ]] || return 1 printf -v "$path_variable" '%s' "" - printf -v "$building_variable" '%s' false + # Callers without a building-state consumer omit this optional output. + if [[ -n "$building_variable" ]]; then + printf -v "$building_variable" "%s" false + fi for (( attempt=1; attempt<=64; attempt++ )); do token=$(xanmod_random_token) || return 1 owner_token=$(xanmod_random_token) || return 1 @@ -1022,13 +1024,11 @@ xanmod_allocate_temp_file() { cleanup_xanmod_active_apt_lists() { if [[ -z "$XANMOD_ACTIVE_APT_LISTS_DIR" ]]; then - XANMOD_ACTIVE_APT_LISTS_BUILDING=false return 0 fi if [[ ! -e "$XANMOD_ACTIVE_APT_LISTS_DIR" && ! -L "$XANMOD_ACTIVE_APT_LISTS_DIR" ]] || remove_xanmod_temp_directory "$XANMOD_ACTIVE_APT_LISTS_DIR" "临时 APT lists"; then XANMOD_ACTIVE_APT_LISTS_DIR="" - XANMOD_ACTIVE_APT_LISTS_BUILDING=false return 0 fi return 1 @@ -1040,8 +1040,7 @@ xanmod_source_is_usable() { local temp_parent="${TMPDIR:-/tmp}" xanmod_allocate_temp_directory XANMOD_ACTIVE_APT_LISTS_DIR \ - XANMOD_ACTIVE_APT_LISTS_BUILDING "$temp_parent" xanmod-apt-lists 0755 || return 1 - XANMOD_ACTIVE_APT_LISTS_BUILDING=false + "" "$temp_parent" xanmod-apt-lists 0755 || return 1 if ! install -d -m 0755 "$XANMOD_ACTIVE_APT_LISTS_DIR/partial"; then cleanup_xanmod_active_apt_lists || true return 1 From b29faef54c08e5e3e93a01cdcf10f42d825c19ea Mon Sep 17 00:00:00 2001 From: LucaLin <78164141+LucaLin233@users.noreply.github.com> Date: Tue, 8 Sep 2026 11:22:50 +0000 Subject: [PATCH 16/21] test(ci): exercise actual workflow lint commands with failure probes --- tests/test-lint-coverage.sh | 61 +++++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 12 deletions(-) diff --git a/tests/test-lint-coverage.sh b/tests/test-lint-coverage.sh index 28097cb..bb14d00 100644 --- a/tests/test-lint-coverage.sh +++ b/tests/test-lint-coverage.sh @@ -1,22 +1,59 @@ #!/usr/bin/env bash set -euo pipefail -# Inert local Git fixture only; never execute production scripts. +# Execute only the workflow lint block against inert files and a ShellCheck spy. +ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) unset GH_TOKEN GITHUB_TOKEN SSH_PRIVATE_KEY_B64 export GIT_CONFIG_NOSYSTEM=1 GIT_CONFIG_GLOBAL=/dev/null unset GIT_DIR GIT_WORK_TREE GIT_INDEX_FILE GIT_CONFIG_COUNT root=$(mktemp -d) -trap "rm -rf -- \"$root\"" EXIT -git init -q "$root" -cd "$root" +cleanup() { rm -rf -- "$root"; } +trap cleanup EXIT +# Fail closed if the named step or its literal block changes shape. +awk ' + /^ - name: Run ShellCheck$/ { found++; step=1; next } + step && /^ run: \|$/ { block=1; next } + block && /^ / { print substr($0, 11); lines++; next } + block { step=0; block=0 } + END { if (found != 1 || lines == 0) exit 1 } +' "$ROOT_DIR/.github/workflows/shell-tests.yml" > "$root/lint.sh" +mkdir -p "$root/bin" "$root/repo" +cat > "$root/bin/shellcheck" <<'STUB' +#!/usr/bin/env bash +set -euo pipefail +[[ $1 == -x && $3 == -- && $# -gt 3 ]] || exit 90 +level=$2 +shift 3 +for path; do printf "%s\t%s\n" "$level" "$path" >> "$CAPTURE"; done +case $level in + --severity=warning) exit "$PRODUCTION_STATUS" ;; + --severity=error) exit "$TEST_STATUS" ;; + *) exit 91 ;; +esac +STUB +chmod +x "$root/bin/shellcheck" +export PATH="$root/bin:$PATH" CAPTURE="$root/capture" +cd "$root/repo" +git init -q mkdir -p new/deep tests/nested touch entry.sh new/deep/production.sh "new/space name.sh" tests/direct.sh tests/nested/deep.sh ignored.zsh git add . touch untracked.sh -mapfile -d "" -t production < <(git ls-files -z -- "*.sh" ":!:tests/**") -mapfile -d "" -t tests < <(git ls-files -z -- "tests/*.sh") -[[ ${#production[@]} == 3 && ${#tests[@]} == 2 ]] -[[ ${production[0]} == entry.sh ]] -[[ ${production[1]} == new/deep/production.sh ]] -[[ ${production[2]} == "new/space name.sh" ]] -[[ ${tests[0]} == tests/direct.sh && ${tests[1]} == tests/nested/deep.sh ]] -printf "PASS: recursive tracked production/test lint coverage\n" +printf "%s\n" \ + $'--severity=warning\tentry.sh' \ + $'--severity=warning\tnew/deep/production.sh' \ + $'--severity=warning\tnew/space name.sh' \ + $'--severity=error\ttests/direct.sh' \ + $'--severity=error\ttests/nested/deep.sh' > "$root/expected" +for PRODUCTION_STATUS in 0 1; do + for TEST_STATUS in 0 1; do + export PRODUCTION_STATUS TEST_STATUS + : > "$CAPTURE" + status=0 + bash --noprofile --norc -e -o pipefail "$root/lint.sh" || status=$? + expected=0 + if (( PRODUCTION_STATUS != 0 || TEST_STATUS != 0 )); then expected=1; fi + [[ $status == "$expected" ]] + diff -u "$root/expected" "$CAPTURE" + printf "PASS: workflow lint production=%s tests=%s exit=%s\n" "$PRODUCTION_STATUS" "$TEST_STATUS" "$status" + done +done From 0640c32e45ba8b609d6ffbb32f406fa15086117e Mon Sep 17 00:00:00 2001 From: LucaLin <78164141+LucaLin233@users.noreply.github.com> Date: Tue, 8 Sep 2026 11:23:27 +0000 Subject: [PATCH 17/21] docs(lint): explain local source and trap exceptions --- linux_setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux_setup.sh b/linux_setup.sh index 6ca3c06..8a9e35b 100755 --- a/linux_setup.sh +++ b/linux_setup.sh @@ -208,7 +208,7 @@ pre_check() { local version_id local major_version - # shellcheck disable=SC1091 + # shellcheck disable=SC1091 # /etc/os-release is provided by the target OS, not this repository. . /etc/os-release os_id="${ID:-}" version_id="${VERSION_ID:-}" From e3a9e8785793ab3677e19bfb0cc8bf40656c28c8 Mon Sep 17 00:00:00 2001 From: LucaLin <78164141+LucaLin233@users.noreply.github.com> Date: Tue, 8 Sep 2026 11:23:27 +0000 Subject: [PATCH 18/21] docs(lint): explain local source and trap exceptions --- modules/docker-setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/docker-setup.sh b/modules/docker-setup.sh index cd06c52..f0703f8 100644 --- a/modules/docker-setup.sh +++ b/modules/docker-setup.sh @@ -121,7 +121,7 @@ detect_supported_distribution() { local version_id local major_version - # shellcheck disable=SC1091 + # shellcheck disable=SC1091 # /etc/os-release is provided by the target OS, not this repository. . /etc/os-release os_id="${ID:-}" version_id="${VERSION_ID:-}" From 487a2b05e300dcb8350f5a6a380de6dab0faaaee Mon Sep 17 00:00:00 2001 From: LucaLin <78164141+LucaLin233@users.noreply.github.com> Date: Tue, 8 Sep 2026 11:23:28 +0000 Subject: [PATCH 19/21] docs(lint): explain local source and trap exceptions --- modules/system-optimize.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/system-optimize.sh b/modules/system-optimize.sh index ee4b15a..1ad5b76 100644 --- a/modules/system-optimize.sh +++ b/modules/system-optimize.sh @@ -333,7 +333,7 @@ get_ubuntu_kernel_meta_package() { kernel_version=$(uname -r) if [[ -r /etc/os-release ]]; then - # shellcheck disable=SC1091 + # shellcheck disable=SC1091 # /etc/os-release is provided by the target OS, not this repository. . /etc/os-release version_id="${VERSION_ID:-}" fi @@ -400,7 +400,7 @@ ensure_zram_kernel_module() { kernel_version=$(uname -r) if [[ -r /etc/os-release ]]; then - # shellcheck disable=SC1091 + # shellcheck disable=SC1091 # /etc/os-release is provided by the target OS, not this repository. . /etc/os-release os_id="${ID:-}" fi From 29cf755054d9535f5b7c278637b32a7a3d02d173 Mon Sep 17 00:00:00 2001 From: LucaLin <78164141+LucaLin233@users.noreply.github.com> Date: Tue, 8 Sep 2026 11:23:29 +0000 Subject: [PATCH 20/21] docs(lint): explain local source and trap exceptions --- modules/system-customize.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/system-customize.sh b/modules/system-customize.sh index dc5a670..ac8d972 100644 --- a/modules/system-customize.sh +++ b/modules/system-customize.sh @@ -2165,7 +2165,7 @@ get_locale_config_file() { local major_version="" if [[ -r /etc/os-release ]]; then - # shellcheck disable=SC1091 + # shellcheck disable=SC1091 # /etc/os-release is provided by the target OS, not this repository. . /etc/os-release os_id="${ID:-}" version_id="${VERSION_ID:-}" @@ -2280,7 +2280,7 @@ authorize_xanmod_install() { } get_os_codename() { if [[ -r "$XANMOD_OS_RELEASE" ]]; then - # shellcheck disable=SC1090 + # shellcheck disable=SC1090 # Runtime OS-release path; test mode substitutes an isolated fixture. . "$XANMOD_OS_RELEASE" if [[ -n "${VERSION_CODENAME:-}" ]]; then echo "$VERSION_CODENAME" @@ -4291,7 +4291,7 @@ restore_xanmod_saved_trap() { trap - "$signal_name" if [[ -n "$trap_definition" ]]; then - # shellcheck disable=SC2294 + # shellcheck disable=SC2294 # Restore shell-quoted code captured by trap -p; eval is intentional. eval "$trap_definition" fi } From c5fde00db2a2aa86a495f37adb7121d372b25f69 Mon Sep 17 00:00:00 2001 From: LucaLin <78164141+LucaLin233@users.noreply.github.com> Date: Tue, 8 Sep 2026 11:23:30 +0000 Subject: [PATCH 21/21] docs(lint): explain local source and trap exceptions --- tools/xanmod-install.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/xanmod-install.sh b/tools/xanmod-install.sh index d5f115f..98179ec 100755 --- a/tools/xanmod-install.sh +++ b/tools/xanmod-install.sh @@ -184,7 +184,7 @@ ensure_package() { } get_os_codename() { if [[ -r "$XANMOD_OS_RELEASE" ]]; then - # shellcheck disable=SC1090 + # shellcheck disable=SC1090 # Runtime OS-release path; test mode substitutes an isolated fixture. . "$XANMOD_OS_RELEASE" if [[ -n "${VERSION_CODENAME:-}" ]]; then echo "$VERSION_CODENAME" @@ -1226,7 +1226,7 @@ restore_xanmod_saved_trap() { trap - "$signal_name" if [[ -n "$trap_definition" ]]; then - # shellcheck disable=SC2294 + # shellcheck disable=SC2294 # Restore shell-quoted code captured by trap -p; eval is intentional. eval "$trap_definition" fi }