Files

135 lines
3.9 KiB
Bash
Executable File

#!/usr/bin/env bash
# Compare two environment dumps from dump-environment.sh
# Usage: ./scripts/compare-environment.sh FILE_A FILE_B
set -euo pipefail
if [[ $# -ne 2 ]]; then
echo "Usage: $0 FILE_A FILE_B" >&2
exit 1
fi
FILE_A="$1"
FILE_B="$2"
for f in "$FILE_A" "$FILE_B"; do
if [[ ! -f "$f" ]]; then
echo "Missing file: $f" >&2
exit 1
fi
done
parse_dump() {
local file="$1"
awk -F= '
/^\[/ {
section = substr($0, 2, length($0) - 2)
next
}
/^[[:space:]]*$/ { next }
/^#/ { next }
{
key = $1
$1 = ""
sub(/^=/, "", $0)
full = (section == "" ? key : section "." key)
print full "\t" $0
}
' "$file" | sort -u
}
TMP_A="$(mktemp)"
TMP_B="$(mktemp)"
TMP_JOIN="$(mktemp)"
trap 'rm -f "$TMP_A" "$TMP_B" "$TMP_JOIN"' EXIT
parse_dump "$FILE_A" >"$TMP_A"
parse_dump "$FILE_B" >"$TMP_B"
join -t $'\t' -a 1 -a 2 -e '—' -o '0,1.2,2.2' "$TMP_A" "$TMP_B" >"$TMP_JOIN"
ONLY_A=0
ONLY_B=0
DIFF=0
SAME=0
echo "Comparing:"
echo " A: $FILE_A"
echo " B: $FILE_B"
echo
while IFS=$'\t' read -r key val_a val_b; do
[[ -z "$key" ]] && continue
if [[ "$val_a" == "—" ]]; then
ONLY_B=$((ONLY_B + 1))
printf ' + %-40s B=%s\n' "$key" "$val_b"
elif [[ "$val_b" == "—" ]]; then
ONLY_A=$((ONLY_A + 1))
printf ' - %-40s A=%s\n' "$key" "$val_a"
elif [[ "$val_a" != "$val_b" ]]; then
DIFF=$((DIFF + 1))
printf ' ≠ %-40s\n A=%s\n B=%s\n' "$key" "$val_a" "$val_b"
else
SAME=$((SAME + 1))
fi
done <"$TMP_JOIN"
echo
echo "Summary: same=$SAME different=$DIFF only_in_A=$ONLY_A only_in_B=$ONLY_B"
# High-signal keys for the common "works on one NixOS box" case.
echo
echo "High-signal differences (if any):"
HIGH_SIGNAL=0
while IFS=$'\t' read -r key val_a val_b; do
[[ "$val_a" == "$val_b" ]] && continue
case "$key" in
meta.flake_lock_sha256|meta.nixpkgs_locked_rev|meta.npm_lock_sha256|meta.git_rev|\
installed_app.psysonic_realpath|installed_app.psysonic_closure_paths|installed_app.psysonic_drv|\
runtime_env.HTTP_PROXY|runtime_env.HTTPS_PROXY|runtime_env.http_proxy|runtime_env.https_proxy|\
runtime_env.NO_PROXY|runtime_env.no_proxy|runtime_env.SSL_CERT_FILE|runtime_env.NIX_SSL_CERT_FILE|\
toolchain_nix_develop.node_realpath|toolchain_nix_develop.rustc_realpath|\
host.nixos_version|host.uname|\
app_config_paths.data_dir|app_config_paths.localstorage_db_path|\
app_preferences.language|app_servers.active_server_id|app_servers.server_count|\
app_servers.server.*.url|app_servers.server.*.alternateUrl|\
app_servers.server.*.customHeaders_count|app_servers.server.*.customHeadersApplyTo|\
app_servers.server.*.password_sha256|app_servers.server.*.customHeaders.*.name|\
app_servers.server.*.customHeaders.*.value_sha256|\
app_network_probe.probe.*)
HIGH_SIGNAL=$((HIGH_SIGNAL + 1))
printf ' ! %s\n A=%s\n B=%s\n' "$key" "$val_a" "$val_b"
;;
esac
done <"$TMP_JOIN"
if [[ "$HIGH_SIGNAL" -eq 0 && "$DIFF" -eq 0 && "$ONLY_A" -eq 0 && "$ONLY_B" -eq 0 ]]; then
echo " (none — environments match on recorded keys)"
elif [[ "$HIGH_SIGNAL" -eq 0 ]]; then
echo " (no high-signal keys differ; see full list above — may be npm patch-level deps only)"
fi
echo
echo "Server / network config differences:"
SERVER_DIFF=0
while IFS=$'\t' read -r key val_a val_b; do
[[ "$val_a" == "$val_b" ]] && continue
case "$key" in
app_servers.*|app_network_probe.*|app_config_paths.*|app_preferences.*)
SERVER_DIFF=$((SERVER_DIFF + 1))
printf ' • %s\n A=%s\n B=%s\n' "$key" "$val_a" "$val_b"
;;
esac
done <"$TMP_JOIN"
if [[ "$SERVER_DIFF" -eq 0 ]]; then
echo " (none — server URLs, headers, and curl probes match)"
fi
echo
echo "Reminder: server offline is usually URL/network/headers, not Node patch versions."
echo "Next: curl the Navidrome URL from both hosts; compare Settings → Servers side by side."
if [[ "$DIFF" -gt 0 || "$ONLY_A" -gt 0 || "$ONLY_B" -gt 0 ]]; then
exit 1
fi