Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
- Floating major tag for the GitHub Action: the release process now force-moves `v0` to each release, so workflows can pin `TypedDevs/bashunit@v0` to track the latest release within a major (#700)
- `bashunit init` now scaffolds a `.github/workflows/tests.yml` CI workflow using the official action (existing files are left untouched) (#702)

### Changed
- `install.sh` now verifies the release checksum by default (set `BASHUNIT_VERIFY_CHECKSUM=false` to opt out); it soft-skips with a warning when a checksum asset is unavailable unless verification was explicitly requested (#703)

## [0.38.0](https://github.com/TypedDevs/bashunit/compare/0.37.0...0.38.0) - 2026-06-07

### Added
Expand Down
7 changes: 7 additions & 0 deletions docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ curl -s https://bashunit.typeddevs.com/install.sh | bash

This will create a file inside a lib folder, such as `lib/bashunit`.

::: tip Automatic checksum verification
`install.sh` verifies the download against the release `checksum` asset by default and
aborts on a mismatch, so a tampered or corrupted download never lands. Set
`BASHUNIT_VERIFY_CHECKSUM=false` to opt out (e.g. for old releases published before
checksum assets existed). The manual check below is only needed when you opt out.
:::

#### Verify

```bash-vue
Expand Down
47 changes: 34 additions & 13 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,31 @@ function compute_sha256() {
# Verify the downloaded 'bashunit' file against the release 'checksum' asset.
# Arguments: $1 - the bashunit download URL. Exits 1 (and removes the binary)
# on any failure so a tampered or unverifiable download never looks successful.
# Handle an inability to verify (missing sha256 tool or checksum asset).
# Strict (fails) when the user explicitly opted in; a soft warning otherwise,
# so installing older releases published before checksum assets existed keeps
# working while a tampered binary (checksum mismatch) is always rejected.
function cannot_verify() {
local reason=$1
if [ "${VERIFY_CHECKSUM_EXPLICIT:-false}" = "true" ]; then
echo "Error: $reason" >&2
rm -f bashunit
exit 1
fi
echo "> Skipping checksum verification: $reason" >&2
}

function verify_checksum() {
local url=$1
local checksum_url="${url%/bashunit}/checksum"

local actual
actual=$(compute_sha256 bashunit)
if [ -z "$actual" ]; then
cannot_verify "no sha256 tool (shasum/sha256sum) available to verify checksum"
return
fi

local expected
if command -v curl >/dev/null 2>&1; then
expected=$(curl -fsSL --retry 3 --retry-delay 2 "$checksum_url" 2>/dev/null | awk '{print $1}')
Expand All @@ -36,17 +57,8 @@ function verify_checksum() {
fi

if [ -z "$expected" ]; then
echo "Error: could not download checksum from $checksum_url" >&2
rm -f bashunit
exit 1
fi

local actual
actual=$(compute_sha256 bashunit)
if [ -z "$actual" ]; then
echo "Error: no sha256 tool (shasum/sha256sum) available to verify checksum" >&2
rm -f bashunit
exit 1
cannot_verify "could not download checksum from $checksum_url"
return
fi

if [ "$actual" != "$expected" ]; then
Expand All @@ -57,7 +69,7 @@ function verify_checksum() {
exit 1
fi

echo "> Checksum verified ($actual)"
echo "> Checksum verified ($actual)" >&2
}

function build_and_install_beta() {
Expand Down Expand Up @@ -108,7 +120,7 @@ function install() {
exit 1
fi

if [ "${BASHUNIT_VERIFY_CHECKSUM:-false}" = "true" ]; then
if [ "$VERIFY_CHECKSUM" = "true" ]; then
verify_checksum "$url"
fi

Expand All @@ -123,6 +135,15 @@ function install() {
DIR="lib"
VERSION="latest"

# Checksum verification is on by default. Track whether the user set it
# explicitly so we can be strict on opt-in and lenient on the default.
if [ -n "${BASHUNIT_VERIFY_CHECKSUM+x}" ]; then
VERIFY_CHECKSUM_EXPLICIT="true"
else
VERIFY_CHECKSUM_EXPLICIT="false"
fi
VERIFY_CHECKSUM="${BASHUNIT_VERIFY_CHECKSUM:-true}"

function is_version() {
regex_match "$1" '^[0-9]+\.[0-9]+\.[0-9]+$' || [[ "$1" == "latest" || "$1" == "beta" ]]
}
Expand Down
21 changes: 21 additions & 0 deletions tests/acceptance/install_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,27 @@ function test_install_verifies_checksum_when_enabled() {
"$(./tmp_install/bashunit --version)"
}

function test_install_verifies_checksum_by_default() {
if [[ "$ACTIVE_INTERNET" -eq 1 ]]; then
bashunit::skip "no internet connection" && return
fi
if [[ "$HAS_DOWNLOADER" -eq 0 ]]; then
bashunit::skip "curl or wget not installed" && return
fi
if ! command -v shasum >/dev/null 2>&1 && ! command -v sha256sum >/dev/null 2>&1; then
bashunit::skip "no sha256 tool available" && return
fi

local output
output="$(./install.sh tmp_install 0.38.0 2>&1)"

if [ ! -f "./tmp_install/bashunit" ]; then
bashunit::skip "transient download failure" && return
fi
assert_contains "Checksum verified" "$output"
assert_file_exists "./tmp_install/bashunit"
}

function test_install_downloads_the_given_version() {
if [[ "$ACTIVE_INTERNET" -eq 1 ]]; then
bashunit::skip "no internet connection" && return
Expand Down
Loading