Skip to content

Commit 73a5a5e

Browse files
authored
Merge pull request #617 from TypedDevs/fix/env-example-comment-spacing
ci: validate .env.example by copying it before test runs
2 parents 4b2a486 + c7ffe3b commit 73a5a5e

15 files changed

+157
-43
lines changed

.env.example

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,54 +7,54 @@
77
#───────────────────────────────────────────────────────────────────────────────
88
# Test Discovery
99
#───────────────────────────────────────────────────────────────────────────────
10-
BASHUNIT_DEFAULT_PATH= # Default: tests
11-
BASHUNIT_BOOTSTRAP= # Default: tests/bootstrap.sh
12-
BASHUNIT_BOOTSTRAP_ARGS= # Arguments passed to bootstrap script
10+
BASHUNIT_DEFAULT_PATH= # Default: tests
11+
BASHUNIT_BOOTSTRAP= # Default: tests/bootstrap.sh
12+
BASHUNIT_BOOTSTRAP_ARGS= # Arguments passed to bootstrap script
1313

1414
#───────────────────────────────────────────────────────────────────────────────
1515
# Output Display
1616
#───────────────────────────────────────────────────────────────────────────────
17-
BASHUNIT_SHOW_HEADER= # Default: true
18-
BASHUNIT_HEADER_ASCII_ART= # Default: false
19-
BASHUNIT_SIMPLE_OUTPUT= # Default: false (use dots instead of test names)
20-
BASHUNIT_VERBOSE= # Default: false (show environment variables)
21-
BASHUNIT_NO_OUTPUT= # Default: false (suppress all output)
22-
BASHUNIT_SHOW_EXECUTION_TIME= # Default: true
23-
BASHUNIT_SHOW_SKIPPED= # Default: false (show skipped test details)
24-
BASHUNIT_SHOW_INCOMPLETE= # Default: false (show incomplete test details)
25-
BASHUNIT_FAILURES_ONLY= # Default: false (only show failures)
26-
BASHUNIT_NO_COLOR= # Default: false (disable colors)
17+
BASHUNIT_SHOW_HEADER= # Default: true
18+
BASHUNIT_HEADER_ASCII_ART= # Default: false
19+
BASHUNIT_SIMPLE_OUTPUT= # Default: false (use dots instead of test names)
20+
BASHUNIT_VERBOSE= # Default: false (show environment variables)
21+
BASHUNIT_NO_OUTPUT= # Default: false (suppress all output)
22+
BASHUNIT_SHOW_EXECUTION_TIME= # Default: true
23+
BASHUNIT_SHOW_SKIPPED= # Default: false (show skipped test details)
24+
BASHUNIT_SHOW_INCOMPLETE= # Default: false (show incomplete test details)
25+
BASHUNIT_FAILURES_ONLY= # Default: false (only show failures)
26+
BASHUNIT_NO_COLOR= # Default: false (disable colors)
2727

2828
#───────────────────────────────────────────────────────────────────────────────
2929
# Test Execution
3030
#───────────────────────────────────────────────────────────────────────────────
31-
BASHUNIT_PARALLEL_RUN= # Default: false
32-
BASHUNIT_STOP_ON_FAILURE= # Default: false (stop suite on first failure)
31+
BASHUNIT_PARALLEL_RUN= # Default: false
32+
BASHUNIT_STOP_ON_FAILURE= # Default: false (stop suite on first failure)
3333
BASHUNIT_STOP_ON_ASSERTION_FAILURE= # Default: true (stop test on first assertion fail)
34-
BASHUNIT_STRICT_MODE= # Default: false (enable set -euo pipefail)
35-
BASHUNIT_LOGIN_SHELL= # Default: false (source login shell profiles)
34+
BASHUNIT_STRICT_MODE= # Default: false (enable set -euo pipefail)
35+
BASHUNIT_LOGIN_SHELL= # Default: false (source login shell profiles)
3636

3737
#───────────────────────────────────────────────────────────────────────────────
3838
# Reports
3939
#───────────────────────────────────────────────────────────────────────────────
40-
BASHUNIT_LOG_JUNIT= # JUnit XML report path (e.g., report.xml)
41-
BASHUNIT_REPORT_HTML= # HTML test report path (e.g., report.html)
40+
BASHUNIT_LOG_JUNIT= # JUnit XML report path (e.g., report.xml)
41+
BASHUNIT_REPORT_HTML= # HTML test report path (e.g., report.html)
4242

4343
#───────────────────────────────────────────────────────────────────────────────
4444
# Code Coverage
4545
#───────────────────────────────────────────────────────────────────────────────
46-
BASHUNIT_COVERAGE= # Default: false
47-
BASHUNIT_COVERAGE_PATHS= # Default: src/ (comma-separated paths to track)
48-
BASHUNIT_COVERAGE_EXCLUDE= # Default: tests/*,vendor/*,*_test.sh,*Test.sh
49-
BASHUNIT_COVERAGE_REPORT= # Default: coverage/lcov.info
50-
BASHUNIT_COVERAGE_REPORT_HTML= # HTML coverage report directory (e.g., coverage/html)
51-
BASHUNIT_COVERAGE_MIN= # Minimum coverage % (fails if below)
52-
BASHUNIT_COVERAGE_THRESHOLD_LOW= # Default: 50 (red below this)
53-
BASHUNIT_COVERAGE_THRESHOLD_HIGH=# Default: 80 (green above this)
46+
BASHUNIT_COVERAGE= # Default: false
47+
BASHUNIT_COVERAGE_PATHS= # Default: src/ (comma-separated paths to track)
48+
BASHUNIT_COVERAGE_EXCLUDE= # Default: tests/*,vendor/*,*_test.sh,*Test.sh
49+
BASHUNIT_COVERAGE_REPORT= # Default: coverage/lcov.info
50+
BASHUNIT_COVERAGE_REPORT_HTML= # HTML coverage report directory (e.g., coverage/html)
51+
BASHUNIT_COVERAGE_MIN= # Minimum coverage % (fails if below)
52+
BASHUNIT_COVERAGE_THRESHOLD_LOW= # Default: 50 (red below this)
53+
BASHUNIT_COVERAGE_THRESHOLD_HIGH= # Default: 80 (green above this)
5454

5555
#───────────────────────────────────────────────────────────────────────────────
5656
# Advanced / Debug
5757
#───────────────────────────────────────────────────────────────────────────────
58-
BASHUNIT_DEV_LOG= # Developer log file path
59-
BASHUNIT_BENCH_MODE= # Default: false (benchmark mode)
60-
BASHUNIT_INTERNAL_LOG= # Default: false (internal debug logging)
58+
BASHUNIT_DEV_LOG= # Developer log file path
59+
BASHUNIT_BENCH_MODE= # Default: false (benchmark mode)
60+
BASHUNIT_INTERNAL_LOG= # Default: false (internal debug logging)

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ jobs:
8080
with:
8181
fetch-depth: 1
8282

83+
- name: Setup Config
84+
run: cp .env.example .env
85+
8386
- name: Download Docker image artifact
8487
uses: actions/download-artifact@v4
8588
with:

.github/workflows/tests.yml

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,54 @@ jobs:
1717
with:
1818
fetch-depth: 1
1919

20+
- name: Setup Config
21+
run: cp .env.example .env
22+
2023
- name: Run Tests
2124
run: make test
2225

26+
localized-ubuntu:
27+
name: "Ubuntu - ${{ matrix.name }} Locale"
28+
runs-on: ubuntu-latest
29+
timeout-minutes: 10
30+
strategy:
31+
fail-fast: false
32+
matrix:
33+
include:
34+
- name: "Spanish"
35+
lang: "es_ES.UTF-8"
36+
tz: "Europe/Madrid"
37+
language_pack: "language-pack-es-base"
38+
- name: "Brazilian"
39+
lang: "pt_BR.UTF-8"
40+
tz: "America/Sao_Paulo"
41+
language_pack: "language-pack-pt-base"
42+
- name: "Japanese"
43+
lang: "ja_JP.UTF-8"
44+
tz: "Asia/Tokyo"
45+
language_pack: "language-pack-ja-base"
46+
steps:
47+
- name: Checkout
48+
uses: actions/checkout@v4
49+
with:
50+
fetch-depth: 1
51+
52+
- name: Install locales
53+
run: |
54+
sudo apt-get update
55+
sudo apt-get install -y locales "${{ matrix.language_pack }}"
56+
sudo locale-gen "${{ matrix.lang }}"
57+
58+
- name: Setup Config
59+
run: cp .env.example .env
60+
61+
- name: Run Tests
62+
env:
63+
LANG: ${{ matrix.lang }}
64+
LC_ALL: ${{ matrix.lang }}
65+
TZ: ${{ matrix.tz }}
66+
run: make test
67+
2368
macos:
2469
name: "macOS - latest"
2570
runs-on: macos-latest
@@ -30,6 +75,9 @@ jobs:
3075
with:
3176
fetch-depth: 1
3277

78+
- name: Setup Config
79+
run: cp .env.example .env
80+
3381
- name: Run Tests
3482
run: make test
3583

@@ -63,6 +111,10 @@ jobs:
63111
with:
64112
fetch-depth: 1
65113

114+
- name: Setup Config
115+
shell: bash
116+
run: cp .env.example .env
117+
66118
- name: Run tests
67119
shell: bash
68120
run: |
@@ -78,6 +130,9 @@ jobs:
78130
with:
79131
fetch-depth: 1
80132

133+
- name: Setup Config
134+
run: cp .env.example .env
135+
81136
- name: Run Tests
82137
run: |
83138
docker run --rm -v "$(pwd)":/project alpine:latest /bin/sh -c " \
@@ -97,6 +152,9 @@ jobs:
97152
with:
98153
fetch-depth: 1
99154

155+
- name: Setup Config
156+
run: cp .env.example .env
157+
100158
- name: Run Tests
101159
run: |
102160
./bashunit --simple tests/
@@ -111,6 +169,9 @@ jobs:
111169
with:
112170
fetch-depth: 1
113171

172+
- name: Setup Config
173+
run: cp .env.example .env
174+
114175
- name: Run Tests
115176
run: |
116177
./bashunit --parallel --simple tests/
@@ -125,6 +186,9 @@ jobs:
125186
with:
126187
fetch-depth: 1
127188

189+
- name: Setup Config
190+
run: cp .env.example .env
191+
128192
- name: Run Tests
129193
run: |
130194
./bashunit --parallel tests/
@@ -139,6 +203,9 @@ jobs:
139203
with:
140204
fetch-depth: 1
141205

206+
- name: Setup Config
207+
run: cp .env.example .env
208+
142209
- name: Run Tests with strict mode
143210
run: |
144211
./bashunit --parallel --simple --strict tests/

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
### Fixed
1010
- Fix spying on `echo` or `printf` causing bashunit to hang due to infinite recursion (#607)
11+
- Fix invalid `.env.example` coverage threshold entry and copy `.env.example` to `.env` in CI test workflows so configuration parse errors are caught during automated test runs
12+
- Fix `clock::now` shell-time parsing when `EPOCHREALTIME` uses a comma decimal separator
1113

1214
## [0.34.1](https://github.com/TypedDevs/bashunit/compare/0.34.0...0.34.1) - 2026-03-20
1315

src/assert_dates.sh

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,25 @@ function bashunit::date::to_epoch() {
1212
;;
1313
esac
1414

15-
# Normalize ISO 8601: replace T with space, strip Z suffix, strip tz offset
15+
# Handle Z (UTC) suffix explicitly: BusyBox needs TZ=UTC, BSD needs +0000
16+
case "$input" in
17+
*Z)
18+
local utc_input="${input%Z}"
19+
local utc_norm="${utc_input/T/ }"
20+
local epoch
21+
# GNU/BusyBox: parse in explicit UTC
22+
epoch=$(TZ=UTC date -d "$utc_input" +%s 2>/dev/null) && { echo "$epoch"; return 0; }
23+
epoch=$(TZ=UTC date -d "$utc_norm" +%s 2>/dev/null) && { echo "$epoch"; return 0; }
24+
# BSD: use +0000 offset which %z understands
25+
epoch=$(date -j -f "%Y-%m-%dT%H:%M:%S%z" "${utc_input}+0000" +%s 2>/dev/null) && { echo "$epoch"; return 0; }
26+
echo "$input"
27+
return 1
28+
;;
29+
esac
30+
31+
# Normalize ISO 8601: replace T with space, strip tz offset
1632
local normalized="$input"
1733
normalized="${normalized/T/ }"
18-
normalized="${normalized%Z}"
1934
# Strip timezone offset (+HHMM or -HHMM) at end for initial parsing
2035
case "$normalized" in
2136
*[+-][0-9][0-9][0-9][0-9])
@@ -30,6 +45,24 @@ function bashunit::date::to_epoch() {
3045
echo "$epoch"
3146
return 0
3247
}
48+
# If input has timezone offset, parse in UTC and adjust manually (BusyBox)
49+
case "$input" in
50+
*[+-][0-9][0-9][0-9][0-9])
51+
epoch=$(TZ=UTC date -d "$normalized" +%s 2>/dev/null) && {
52+
local ilen=${#input}
53+
local ostart=$((ilen - 5))
54+
local osign="${input:$ostart:1}"
55+
local ohh="${input:$((ostart + 1)):2}"
56+
local omm="${input:$((ostart + 3)):2}"
57+
local osecs=$(( (10#$ohh * 3600) + (10#$omm * 60) ))
58+
if [ "$osign" = "+" ]; then
59+
osecs=$(( -osecs ))
60+
fi
61+
echo $(( epoch + osecs ))
62+
return 0
63+
}
64+
;;
65+
esac
3366
# Try GNU date with normalized (space-separated) input
3467
if [ "$normalized" != "$input" ]; then
3568
epoch=$(date -d "$normalized" +%s 2>/dev/null) && {

src/clock.sh

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,11 @@ EOF
113113
shell)
114114
# shellcheck disable=SC2155
115115
local shell_time="$(bashunit::clock::shell_time)"
116-
local seconds="${shell_time%%.*}"
117-
local microseconds="${shell_time#*.}"
116+
local seconds="${shell_time%%[.,]*}"
117+
local microseconds="${shell_time#*[.,]}"
118+
if [ "$seconds" = "$shell_time" ]; then
119+
microseconds=""
120+
fi
118121
# Pad to 6 digits and strip leading zeros for arithmetic
119122
microseconds="${microseconds}000000"
120123
microseconds="${microseconds:0:6}"

tests/acceptance/bashunit_bootstrap_args_test.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ function test_bootstrap_args_via_env_variable() {
2626
# Use --env flag to set the bootstrap file (avoiding .env override),
2727
# but use BASHUNIT_BOOTSTRAP_ARGS from environment
2828
output=$(BASHUNIT_BOOTSTRAP_ARGS="hello world" \
29-
./bashunit --no-parallel --simple \
29+
./bashunit --no-parallel --simple --skip-env-file \
3030
--env "tests/acceptance/fixtures/bootstrap_with_args.sh" \
3131
tests/acceptance/fixtures/test_bootstrap_args.sh 2>&1) || true
3232

tests/acceptance/bashunit_execution_error_test.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ function test_bashunit_when_a_execution_error() {
2525
printf "%sRunning ./tests/acceptance/fixtures/test_bashunit_when_a_execution_error.sh%s\n" \
2626
"${color_bold}" "${color_default}"
2727
printf "%s✗ Error%s: Error\n" "${color_red}" "${color_default}"
28-
printf " %sline 4: invalid_function_name: command not found%s\n" "${color_dim}" "${color_default}"
2928
)
3029
local fixture_end=$(
3130
format_summary_title "Tests: "
@@ -39,6 +38,7 @@ function test_bashunit_when_a_execution_error() {
3938

4039
local actual="$(./bashunit --no-parallel --detailed --env "$TEST_ENV_FILE" "$test_file")"
4140
assert_contains "$fixture_start" "$actual"
41+
assert_contains "invalid_function_name" "$actual"
4242
assert_contains "$fixture_end" "$actual"
4343
assert_general_error "$(./bashunit --no-parallel --env "$TEST_ENV_FILE" "$test_file")"
4444
}

tests/acceptance/bashunit_no_color_test.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ function set_up_before_script() {
88
function test_bashunit_no_color_flag_disables_colors() {
99
local test_file=./tests/acceptance/fixtures/test_bashunit_when_a_test_passes.sh
1010
local output
11-
output=$(./bashunit --no-parallel --env "$TEST_ENV_FILE" "$test_file" --no-color --simple)
11+
output=$(./bashunit --no-parallel --skip-env-file --env "$TEST_ENV_FILE" "$test_file" --no-color --simple)
1212

1313
# ANSI escape codes start with \x1b[ (ESC[) - should not be present
1414
assert_not_contains $'\e[' "$output"

tests/acceptance/bashunit_setup_before_script_error_test.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ function test_bashunit_when_set_up_before_script_errors() {
1515

1616
local header_line="Running $fixture"
1717
local error_line="✗ Error: Set up before script"
18-
local message_line=" $fixture: line 4: invalid_function_name: command not found"
18+
local message_line="invalid_function_name"
1919
local tests_summary="Tests: 1 failed, 1 total"
2020
local assertions_summary="Assertions: 0 failed, 0 total"
2121

0 commit comments

Comments
 (0)