Skip to content

Commit ff1f139

Browse files
committed
fix(test): guard release sandbox tests for Bash 3.0.0 compatibility
In unpatched Bash 3.0.0, `return` in a sourced file inside a for loop may not properly return from the source. Use if/else guard to prevent test function definitions when running under Bash 3.0. Also revert debug CI workflow changes.
1 parent 0b54500 commit ff1f139

2 files changed

Lines changed: 143 additions & 144 deletions

File tree

.github/workflows/tests-bash-3.0.yml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,6 @@ jobs:
9494

9595
- name: Run tests with Bash 3.0 (${{ matrix.name }})
9696
run: |
97-
docker run --rm \
98-
-v "$(pwd)":/bashunit \
99-
-w /bashunit \
100-
bashunit-bash3 \
101-
/opt/bash-3.0/bin/bash -c './bashunit ${{ matrix.flags }} tests/ 2>&1; echo "EXIT_CODE=$?"' || true
10297
docker run --rm \
10398
-v "$(pwd)":/bashunit \
10499
-w /bashunit \

tests/unit/release_sandbox_test.sh

Lines changed: 143 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -2,191 +2,195 @@
22

33
# release.sh requires Bash 3.1+ (uses += array syntax)
44
# Skip this entire test file on Bash 3.0
5-
if [[ "${BASH_VERSINFO[0]}" -eq 3 ]] && [[ "${BASH_VERSINFO[1]}" -lt 1 ]]; then
5+
if [ "${BASH_VERSINFO[0]}" -eq 3 ] && [ "${BASH_VERSINFO[1]}" -lt 1 ]; then
66
# shellcheck disable=SC2317
7-
return 0 2>/dev/null || exit 0
8-
fi
7+
return 0 2>/dev/null || true
8+
# Fallback: if return didn't work (Bash 3.0.0 bug in sourced files),
9+
# define no test functions so the runner has nothing to execute
10+
else
911

10-
RELEASE_SCRIPT_DIR=""
12+
RELEASE_SCRIPT_DIR=""
1113

12-
function set_up_before_script() {
13-
RELEASE_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
14+
function set_up_before_script() {
15+
RELEASE_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
1416

15-
# Source release.sh to get access to functions
16-
# shellcheck source=/dev/null
17-
source "$RELEASE_SCRIPT_DIR/release.sh"
18-
}
17+
# Source release.sh to get access to functions
18+
# shellcheck source=/dev/null
19+
source "$RELEASE_SCRIPT_DIR/release.sh"
20+
}
1921

20-
##########################
21-
# Sandbox mode tests
22-
##########################
22+
##########################
23+
# Sandbox mode tests
24+
##########################
2325

24-
function test_sandbox_create_creates_temp_directory() {
25-
release::sandbox::create 2>/dev/null
26-
assert_not_empty "$SANDBOX_DIR"
27-
assert_directory_exists "$SANDBOX_DIR"
28-
rm -rf "$SANDBOX_DIR"
29-
}
26+
function test_sandbox_create_creates_temp_directory() {
27+
release::sandbox::create 2>/dev/null
28+
assert_not_empty "$SANDBOX_DIR"
29+
assert_directory_exists "$SANDBOX_DIR"
30+
rm -rf "$SANDBOX_DIR"
31+
}
3032

31-
function test_sandbox_create_copies_project_files() {
32-
local original_dir
33-
original_dir=$(pwd)
33+
function test_sandbox_create_copies_project_files() {
34+
local original_dir
35+
original_dir=$(pwd)
3436

35-
cd "$RELEASE_SCRIPT_DIR" || return
36-
release::sandbox::create 2>/dev/null
37+
cd "$RELEASE_SCRIPT_DIR" || return
38+
release::sandbox::create 2>/dev/null
3739

38-
# Check that key files were copied
39-
assert_file_exists "$SANDBOX_DIR/bashunit"
40-
assert_file_exists "$SANDBOX_DIR/build.sh"
41-
assert_file_exists "$SANDBOX_DIR/CHANGELOG.md"
40+
# Check that key files were copied
41+
assert_file_exists "$SANDBOX_DIR/bashunit"
42+
assert_file_exists "$SANDBOX_DIR/build.sh"
43+
assert_file_exists "$SANDBOX_DIR/CHANGELOG.md"
4244

43-
rm -rf "$SANDBOX_DIR"
44-
cd "$original_dir" || return
45-
}
45+
rm -rf "$SANDBOX_DIR"
46+
cd "$original_dir" || return
47+
}
4648

47-
function test_sandbox_create_excludes_git_directory() {
48-
local original_dir
49-
original_dir=$(pwd)
49+
function test_sandbox_create_excludes_git_directory() {
50+
local original_dir
51+
original_dir=$(pwd)
5052

51-
cd "$RELEASE_SCRIPT_DIR" || return
52-
release::sandbox::create 2>/dev/null
53+
cd "$RELEASE_SCRIPT_DIR" || return
54+
release::sandbox::create 2>/dev/null
5355

54-
# .git should NOT be copied
55-
assert_directory_not_exists "$SANDBOX_DIR/.git"
56+
# .git should NOT be copied
57+
assert_directory_not_exists "$SANDBOX_DIR/.git"
5658

57-
rm -rf "$SANDBOX_DIR"
58-
cd "$original_dir" || return
59-
}
59+
rm -rf "$SANDBOX_DIR"
60+
cd "$original_dir" || return
61+
}
6062

61-
function test_sandbox_create_excludes_release_state() {
62-
local original_dir
63-
original_dir=$(pwd)
63+
function test_sandbox_create_excludes_release_state() {
64+
local original_dir
65+
original_dir=$(pwd)
6466

65-
cd "$RELEASE_SCRIPT_DIR" || return
67+
cd "$RELEASE_SCRIPT_DIR" || return
6668

67-
# Create a .release-state directory to test exclusion
68-
mkdir -p .release-state/test
69-
release::sandbox::create 2>/dev/null
69+
# Create a .release-state directory to test exclusion
70+
mkdir -p .release-state/test
71+
release::sandbox::create 2>/dev/null
7072

71-
# .release-state should NOT be copied
72-
assert_directory_not_exists "$SANDBOX_DIR/.release-state"
73+
# .release-state should NOT be copied
74+
assert_directory_not_exists "$SANDBOX_DIR/.release-state"
7375

74-
rm -rf "$SANDBOX_DIR" .release-state
75-
cd "$original_dir" || return
76-
}
76+
rm -rf "$SANDBOX_DIR" .release-state
77+
cd "$original_dir" || return
78+
}
7779

78-
function test_sandbox_setup_git_initializes_repo() {
79-
if ! command -v git >/dev/null 2>&1; then
80-
bashunit::skip "git not available" && return
81-
fi
80+
function test_sandbox_setup_git_initializes_repo() {
81+
if ! command -v git >/dev/null 2>&1; then
82+
bashunit::skip "git not available" && return
83+
fi
8284

83-
local original_dir
84-
original_dir=$(pwd)
85+
local original_dir
86+
original_dir=$(pwd)
8587

86-
cd "$RELEASE_SCRIPT_DIR" || return
87-
release::sandbox::create 2>/dev/null
88-
release::sandbox::setup_git 2>/dev/null
88+
cd "$RELEASE_SCRIPT_DIR" || return
89+
release::sandbox::create 2>/dev/null
90+
release::sandbox::setup_git 2>/dev/null
8991

90-
# Should have a .git directory now
91-
assert_directory_exists "$SANDBOX_DIR/.git"
92+
# Should have a .git directory now
93+
assert_directory_exists "$SANDBOX_DIR/.git"
9294

93-
rm -rf "$SANDBOX_DIR"
94-
cd "$original_dir" || return
95-
}
95+
rm -rf "$SANDBOX_DIR"
96+
cd "$original_dir" || return
97+
}
9698

97-
function test_sandbox_setup_git_creates_initial_commit() {
98-
if ! command -v git >/dev/null 2>&1; then
99-
bashunit::skip "git not available" && return
100-
fi
99+
function test_sandbox_setup_git_creates_initial_commit() {
100+
if ! command -v git >/dev/null 2>&1; then
101+
bashunit::skip "git not available" && return
102+
fi
101103

102-
local original_dir
103-
original_dir=$(pwd)
104+
local original_dir
105+
original_dir=$(pwd)
104106

105-
cd "$RELEASE_SCRIPT_DIR" || return
106-
release::sandbox::create 2>/dev/null
107-
release::sandbox::setup_git 2>/dev/null
107+
cd "$RELEASE_SCRIPT_DIR" || return
108+
release::sandbox::create 2>/dev/null
109+
release::sandbox::setup_git 2>/dev/null
108110

109-
# Should have at least one commit
110-
local commit_count
111-
commit_count=$(git -C "$SANDBOX_DIR" rev-list --count HEAD 2>/dev/null || echo "0")
112-
assert_equals "1" "$commit_count"
111+
# Should have at least one commit
112+
local commit_count
113+
commit_count=$(git -C "$SANDBOX_DIR" rev-list --count HEAD 2>/dev/null || echo "0")
114+
assert_equals "1" "$commit_count"
113115

114-
rm -rf "$SANDBOX_DIR"
115-
cd "$original_dir" || return
116-
}
116+
rm -rf "$SANDBOX_DIR"
117+
cd "$original_dir" || return
118+
}
117119

118-
function test_sandbox_mock_gh_handles_release_command() {
119-
release::sandbox::mock_gh 2>/dev/null
120+
function test_sandbox_mock_gh_handles_release_command() {
121+
release::sandbox::mock_gh 2>/dev/null
120122

121-
local result
122-
result=$(gh release create "1.0.0" 2>&1)
123-
assert_contains "SANDBOX" "$result"
123+
local result
124+
result=$(gh release create "1.0.0" 2>&1)
125+
assert_contains "SANDBOX" "$result"
124126

125-
# Unset the mock
126-
unset -f gh
127-
}
127+
# Unset the mock
128+
unset -f gh
129+
}
128130

129-
function test_sandbox_mock_gh_handles_api_command() {
130-
release::sandbox::mock_gh 2>/dev/null
131+
function test_sandbox_mock_gh_handles_api_command() {
132+
release::sandbox::mock_gh 2>/dev/null
131133

132-
local result
133-
result=$(gh api /repos/test 2>&1)
134+
local result
135+
result=$(gh api /repos/test 2>&1)
134136

135-
# Should return empty (not fail)
136-
assert_successful_code
137+
# Should return empty (not fail)
138+
assert_successful_code
137139

138-
unset -f gh
139-
}
140+
unset -f gh
141+
}
140142

141-
function test_sandbox_mock_gh_handles_auth_command() {
142-
release::sandbox::mock_gh 2>/dev/null
143+
function test_sandbox_mock_gh_handles_auth_command() {
144+
release::sandbox::mock_gh 2>/dev/null
143145

144-
# Should succeed (return 0)
145-
gh auth status 2>/dev/null
146-
assert_successful_code
146+
# Should succeed (return 0)
147+
gh auth status 2>/dev/null
148+
assert_successful_code
147149

148-
unset -f gh
149-
}
150+
unset -f gh
151+
}
150152

151-
function test_sandbox_mock_git_push_prevents_actual_push() {
152-
if ! command -v git >/dev/null 2>&1; then
153-
bashunit::skip "git not available" && return
154-
fi
153+
function test_sandbox_mock_git_push_prevents_actual_push() {
154+
if ! command -v git >/dev/null 2>&1; then
155+
bashunit::skip "git not available" && return
156+
fi
155157

156-
release::sandbox::mock_git_push 2>/dev/null
158+
release::sandbox::mock_git_push 2>/dev/null
157159

158-
local result
159-
result=$(git push origin main 2>&1)
160-
assert_contains "SANDBOX" "$result"
160+
local result
161+
result=$(git push origin main 2>&1)
162+
assert_contains "SANDBOX" "$result"
161163

162-
# Unset the mock
163-
unset -f git
164-
}
164+
# Unset the mock
165+
unset -f git
166+
}
165167

166-
function test_sandbox_mock_git_push_allows_other_git_commands() {
167-
if ! command -v git >/dev/null 2>&1; then
168-
bashunit::skip "git not available" && return
169-
fi
168+
function test_sandbox_mock_git_push_allows_other_git_commands() {
169+
if ! command -v git >/dev/null 2>&1; then
170+
bashunit::skip "git not available" && return
171+
fi
170172

171-
local temp_dir
172-
temp_dir=$(mktemp -d)
173+
local temp_dir
174+
temp_dir=$(mktemp -d)
173175

174-
(
175-
cd "$temp_dir" || return
176-
git init --quiet
177-
git config user.email "test@test.com"
178-
git config user.name "Test"
179-
echo "test" >file.txt
180-
git add file.txt
176+
(
177+
cd "$temp_dir" || return
178+
git init --quiet
179+
git config user.email "test@test.com"
180+
git config user.name "Test"
181+
echo "test" >file.txt
182+
git add file.txt
181183

182-
release::sandbox::mock_git_push 2>/dev/null
184+
release::sandbox::mock_git_push 2>/dev/null
185+
186+
# Non-push commands should work
187+
git commit -m "test" --quiet
188+
git status --short
189+
) 2>/dev/null
183190

184-
# Non-push commands should work
185-
git commit -m "test" --quiet
186-
git status --short
187-
) 2>/dev/null
191+
assert_successful_code
192+
rm -rf "$temp_dir"
193+
unset -f git 2>/dev/null || true
194+
}
188195

189-
assert_successful_code
190-
rm -rf "$temp_dir"
191-
unset -f git 2>/dev/null || true
192-
}
196+
fi # end of Bash 3.1+ guard

0 commit comments

Comments
 (0)