Skip to content

Commit 56b8481

Browse files
authored
fix(upgrade): exit non-zero with clear error when download fails (#659)
1 parent a6b4a38 commit 56b8481

4 files changed

Lines changed: 160 additions & 9 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
## Unreleased
44

5+
### Fixed
6+
- `bashunit upgrade` no longer reports success when the binary download fails; it now exits non-zero, prints the URL it tried, surfaces the underlying curl/wget error, and validates the downloaded file is non-empty before replacing the binary
7+
58
### Added
69
- `--show-output` displays captured test output on assertion failures (#637)
710
- npm registry distribution: `npm install -g bashunit` ships the prebuilt single-file binary (#244)

src/io.sh

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,11 @@ function bashunit::io::download_to() {
2121
local url="$1"
2222
local output="$2"
2323
if bashunit::dependencies::has_curl; then
24-
curl -L -J -o "$output" "$url" 2>/dev/null
24+
curl -fsSL -o "$output" "$url"
2525
elif bashunit::dependencies::has_wget; then
26-
wget -q -O "$output" "$url" 2>/dev/null
26+
wget -q -O "$output" "$url"
2727
else
28+
echo "no curl or wget available" >&2
2829
return 1
2930
fi
3031
}

src/upgrade.sh

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,54 @@
11
#!/usr/bin/env bash
22

33
function bashunit::upgrade::upgrade() {
4-
local script_path
5-
script_path="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
4+
local install_dir="${BASHUNIT_INSTALL_DIR:-}"
5+
if [ -z "$install_dir" ]; then
6+
install_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7+
fi
8+
local target="$install_dir/bashunit"
9+
610
local latest_tag
711
latest_tag="$(bashunit::helper::get_latest_tag)"
812

13+
if [ -z "$latest_tag" ]; then
14+
echo "Failed to resolve latest bashunit version. Check your internet connection and that 'git' is installed." >&2
15+
return 1
16+
fi
17+
918
if [ "$BASHUNIT_VERSION" = "$latest_tag" ]; then
1019
echo "> You are already on latest version"
11-
return
20+
return 0
1221
fi
1322

1423
echo "> Upgrading bashunit to latest version"
15-
cd "$script_path" || exit
1624

1725
local url="https://github.com/TypedDevs/bashunit/releases/download/$latest_tag/bashunit"
18-
if ! bashunit::io::download_to "$url" "bashunit"; then
19-
echo "Failed to download bashunit"
26+
local err_file
27+
err_file="$(mktemp 2>/dev/null || echo "/tmp/bashunit_upgrade_err.$$")"
28+
local download_status=0
29+
bashunit::io::download_to "$url" "$target" 2>"$err_file" || download_status=$?
30+
31+
if [ "$download_status" -ne 0 ]; then
32+
echo "Failed to download bashunit $latest_tag from $url" >&2
33+
if [ -s "$err_file" ]; then
34+
echo "Reason:" >&2
35+
sed 's/^/ /' "$err_file" >&2
36+
fi
37+
rm -f "$err_file" "$target"
38+
return 1
39+
fi
40+
rm -f "$err_file"
41+
42+
if [ ! -s "$target" ]; then
43+
echo "Failed to download bashunit $latest_tag from $url (empty file)" >&2
44+
rm -f "$target"
45+
return 1
2046
fi
2147

22-
chmod u+x "bashunit"
48+
if ! chmod u+x "$target"; then
49+
echo "Failed to make $target executable" >&2
50+
return 1
51+
fi
2352

2453
echo "> bashunit upgraded successfully to latest version $latest_tag"
2554
}

tests/unit/upgrade_test.sh

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
#!/usr/bin/env bash
2+
3+
# shellcheck disable=SC2329 # Test functions are invoked indirectly by bashunit
4+
5+
function set_up() {
6+
WORK_DIR="$(mktemp -d)"
7+
export BASHUNIT_INSTALL_DIR="$WORK_DIR"
8+
}
9+
10+
function tear_down() {
11+
unset BASHUNIT_INSTALL_DIR
12+
rm -rf "$WORK_DIR"
13+
}
14+
15+
function fake_get_latest_tag() {
16+
echo "9.9.9"
17+
}
18+
19+
function fake_get_empty_tag() {
20+
echo ""
21+
}
22+
23+
function fake_download_fail() {
24+
echo "curl: (6) Could not resolve host: github.com" >&2
25+
return 1
26+
}
27+
28+
function fake_download_success() {
29+
local _url="$1"
30+
local output="$2"
31+
printf '#!/usr/bin/env bash\necho fake\n' >"$output"
32+
}
33+
34+
function fake_download_empty() {
35+
local _url="$1"
36+
local output="$2"
37+
: >"$output"
38+
}
39+
40+
function fake_get_current_tag() {
41+
echo "$BASHUNIT_VERSION"
42+
}
43+
44+
function test_upgrade_aborts_when_download_fails() {
45+
bashunit::mock bashunit::helper::get_latest_tag fake_get_latest_tag
46+
bashunit::mock bashunit::io::download_to fake_download_fail
47+
48+
local output
49+
local exit_code=0
50+
output="$(bashunit::upgrade::upgrade 2>&1)" || exit_code=$?
51+
52+
assert_contains "Failed to download bashunit 9.9.9 from" "$output"
53+
assert_contains "https://github.com/TypedDevs/bashunit/releases/download/9.9.9/bashunit" "$output"
54+
assert_not_contains "upgraded successfully" "$output"
55+
assert_equals "1" "$exit_code"
56+
assert_file_not_exists "$WORK_DIR/bashunit"
57+
}
58+
59+
function test_upgrade_surfaces_underlying_download_error_message() {
60+
bashunit::mock bashunit::helper::get_latest_tag fake_get_latest_tag
61+
bashunit::mock bashunit::io::download_to fake_download_fail
62+
63+
local output
64+
output="$(bashunit::upgrade::upgrade 2>&1)" || true
65+
66+
assert_contains "Reason:" "$output"
67+
assert_contains "Could not resolve host" "$output"
68+
}
69+
70+
function test_upgrade_aborts_when_downloaded_file_is_empty() {
71+
bashunit::mock bashunit::helper::get_latest_tag fake_get_latest_tag
72+
bashunit::mock bashunit::io::download_to fake_download_empty
73+
74+
local output
75+
local exit_code=0
76+
output="$(bashunit::upgrade::upgrade 2>&1)" || exit_code=$?
77+
78+
assert_contains "empty file" "$output"
79+
assert_not_contains "upgraded successfully" "$output"
80+
assert_equals "1" "$exit_code"
81+
assert_file_not_exists "$WORK_DIR/bashunit"
82+
}
83+
84+
function test_upgrade_aborts_when_latest_tag_cannot_be_resolved() {
85+
bashunit::mock bashunit::helper::get_latest_tag fake_get_empty_tag
86+
87+
local output
88+
local exit_code=0
89+
output="$(bashunit::upgrade::upgrade 2>&1)" || exit_code=$?
90+
91+
assert_contains "Failed to resolve latest bashunit version" "$output"
92+
assert_equals "1" "$exit_code"
93+
}
94+
95+
function test_upgrade_reports_success_when_download_succeeds() {
96+
bashunit::mock bashunit::helper::get_latest_tag fake_get_latest_tag
97+
bashunit::mock bashunit::io::download_to fake_download_success
98+
99+
local output
100+
output="$(bashunit::upgrade::upgrade 2>&1)"
101+
102+
assert_contains "Upgrading bashunit to latest version" "$output"
103+
assert_contains "upgraded successfully to latest version 9.9.9" "$output"
104+
assert_not_contains "Failed to download" "$output"
105+
assert_file_exists "$WORK_DIR/bashunit"
106+
assert_successful_code "$([ -x "$WORK_DIR/bashunit" ] && echo 0 || echo 1)"
107+
}
108+
109+
function test_upgrade_skips_when_already_on_latest() {
110+
bashunit::mock bashunit::helper::get_latest_tag fake_get_current_tag
111+
112+
local output
113+
output="$(bashunit::upgrade::upgrade 2>&1)"
114+
115+
assert_contains "You are already on latest version" "$output"
116+
assert_not_contains "Failed to download" "$output"
117+
assert_not_contains "upgraded successfully" "$output"
118+
}

0 commit comments

Comments
 (0)