fix(easy-docker): pin and verify gum fallback release

This commit is contained in:
RocketQuack 2026-04-08 16:44:28 +02:00
parent b4cbab62a5
commit 6d43530ff6
5 changed files with 153 additions and 25 deletions

View file

@ -16,7 +16,8 @@ bash easy-docker.sh
- Docker Desktop includes Compose v2 by default; on Linux Engine-only setups you may need the `docker-compose-plugin` package
- Docker daemon must be running before the TUI starts
- Required docker commands are validated (`docker ps/exec/inspect/cp` and `docker compose config/up/down/logs/exec/pull/ps`)
- If package manager installation for `gum` fails, the script can use a GitHub binary fallback
- If package manager installation for `gum` fails, the script can use a pinned GitHub binary fallback
- The GitHub fallback is pinned to `gum` `v0.17.0` and verifies SHA256 checksums from `scripts/easy-docker/config/gum-checksums.tsv`
## Options

View file

@ -0,0 +1,7 @@
# version asset_name sha256
0.17.0 gum_0.17.0_Darwin_arm64.tar.gz e2a4b8596efa05821d8c58d0c1afbcd7ad1699ba69c689cc3ff23a4a99c8b237
0.17.0 gum_0.17.0_Darwin_x86_64.tar.gz cd66576aeebe6cd19c771863c7e8d696e0e1d5387d1e7075666baa67c2052e53
0.17.0 gum_0.17.0_Linux_arm64.tar.gz b0b9ed95cbf7c8b7073f17b9591811f5c001e33c7cfd066ca83ce8a07c576f9c
0.17.0 gum_0.17.0_Linux_armv7.tar.gz 25711c2fbc6887cde79ed586972834121a04955968808dd688c688381ac50ab2
0.17.0 gum_0.17.0_Linux_x86_64.tar.gz 69ee169bd6387331928864e94d47ed01ef649fbfe875baed1bbf27b5377a6fdb
0.17.0 gum_0.17.0_Windows_x86_64.zip b2be80531c6babc8d4e0e6ca95773d58118a2e1582ae006aace08dbc55503072
1 # version asset_name sha256
2 0.17.0 gum_0.17.0_Darwin_arm64.tar.gz e2a4b8596efa05821d8c58d0c1afbcd7ad1699ba69c689cc3ff23a4a99c8b237
3 0.17.0 gum_0.17.0_Darwin_x86_64.tar.gz cd66576aeebe6cd19c771863c7e8d696e0e1d5387d1e7075666baa67c2052e53
4 0.17.0 gum_0.17.0_Linux_arm64.tar.gz b0b9ed95cbf7c8b7073f17b9591811f5c001e33c7cfd066ca83ce8a07c576f9c
5 0.17.0 gum_0.17.0_Linux_armv7.tar.gz 25711c2fbc6887cde79ed586972834121a04955968808dd688c688381ac50ab2
6 0.17.0 gum_0.17.0_Linux_x86_64.tar.gz 69ee169bd6387331928864e94d47ed01ef649fbfe875baed1bbf27b5377a6fdb
7 0.17.0 gum_0.17.0_Windows_x86_64.zip b2be80531c6babc8d4e0e6ca95773d58118a2e1582ae006aace08dbc55503072

View file

@ -1,5 +1,122 @@
#!/usr/bin/env bash
get_gum_checksums_path() {
local gum_lib_dir=""
gum_lib_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
printf '%s/../../../config/gum-checksums.tsv\n' "${gum_lib_dir}"
}
get_pinned_gum_version() {
local checksums_path=""
local release_version=""
checksums_path="$(get_gum_checksums_path)"
if [ ! -f "${checksums_path}" ]; then
return 1
fi
release_version="$(
awk -F '\t' '
/^[[:space:]]*#/ { next }
NF < 3 { next }
{
print $1
exit
}
' "${checksums_path}"
)"
if [ -z "${release_version}" ]; then
return 1
fi
printf '%s\n' "${release_version}"
}
get_pinned_gum_asset_checksum() {
local release_version="${1}"
local asset_name="${2}"
local checksums_path=""
local expected_checksum=""
checksums_path="$(get_gum_checksums_path)"
if [ ! -f "${checksums_path}" ]; then
return 1
fi
expected_checksum="$(
awk -F '\t' -v release_version="${release_version}" -v asset_name="${asset_name}" '
/^[[:space:]]*#/ { next }
NF < 3 { next }
$1 == release_version && $2 == asset_name {
print $3
exit
}
' "${checksums_path}"
)"
if [ -z "${expected_checksum}" ]; then
return 1
fi
printf '%s\n' "${expected_checksum}"
}
sha256_verification_available() {
command_exists sha256sum ||
command_exists shasum ||
command_exists openssl ||
command_exists certutil
}
compute_file_sha256() {
local file_path="${1}"
local hash_input_path="${file_path}"
if command_exists sha256sum; then
sha256sum "${file_path}" | awk '{print tolower($1)}'
return $?
fi
if command_exists shasum; then
shasum -a 256 "${file_path}" | awk '{print tolower($1)}'
return $?
fi
if command_exists openssl; then
openssl dgst -sha256 -r "${file_path}" | awk '{print tolower($1)}'
return $?
fi
if command_exists certutil; then
if command_exists cygpath; then
hash_input_path="$(cygpath -w "${file_path}" 2>/dev/null || printf '%s' "${file_path}")"
fi
certutil -hashfile "${hash_input_path}" SHA256 2>/dev/null |
awk 'NR == 2 { gsub(/ /, "", $0); print tolower($0); exit }'
return $?
fi
return 1
}
verify_file_sha256() {
local file_path="${1}"
local expected_checksum="${2}"
local actual_checksum=""
actual_checksum="$(compute_file_sha256 "${file_path}" || true)"
if [ -z "${actual_checksum}" ]; then
return 1
fi
if [ "${actual_checksum}" != "$(printf '%s' "${expected_checksum}" | tr '[:upper:]' '[:lower:]')" ]; then
return 1
fi
return 0
}
get_gum_asset_candidates() {
local release_version="${1}"
local gum_os="${2}"
@ -60,23 +177,3 @@ find_gum_binary() {
return 1
}
fetch_latest_gum_release_version() {
local api_payload=""
local tag_name=""
api_payload="$(curl -fsSL "https://api.github.com/repos/charmbracelet/gum/releases/latest")" || return 1
if command_exists jq; then
tag_name="$(printf '%s' "${api_payload}" | jq -r '.tag_name // empty')"
else
tag_name="$(printf '%s' "${api_payload}" | sed -n 's/.*"tag_name":[[:space:]]*"\([^"]*\)".*/\1/p' | head -n 1)"
fi
tag_name="${tag_name#v}"
if [ -z "${tag_name}" ]; then
return 1
fi
printf '%s\n' "${tag_name}"
}

View file

@ -46,7 +46,7 @@ ensure_gum() {
fi
if should_use_github_fallback; then
echo "Trying GitHub release fallback..."
echo "Trying pinned GitHub release fallback..."
if install_gum_from_github_release; then
hash -r
fi

View file

@ -10,6 +10,7 @@ cleanup_gum_tmp_dir() {
install_gum_from_github_release() {
local release_version=""
local checksums_path=""
local asset_name=""
local asset_path=""
local download_url=""
@ -20,6 +21,7 @@ install_gum_from_github_release() {
local target_binary_name="gum"
local gum_os=""
local gum_arch=""
local expected_checksum=""
if ! command_exists curl; then
echo "curl is required for the GitHub fallback."
@ -31,9 +33,20 @@ install_gum_from_github_release() {
return 1
fi
release_version="$(fetch_latest_gum_release_version || true)"
release_version="$(get_pinned_gum_version || true)"
if [ -z "${release_version}" ]; then
echo "Could not determine latest gum release version."
echo "Could not determine the pinned gum release version."
return 1
fi
checksums_path="$(get_gum_checksums_path)"
if [ ! -f "${checksums_path}" ]; then
echo "Pinned gum checksum file is missing: ${checksums_path}"
return 1
fi
if ! sha256_verification_available; then
echo "A SHA256 verification tool is required for the GitHub fallback."
return 1
fi
@ -45,6 +58,11 @@ install_gum_from_github_release() {
extract_dir="${tmp_dir}/extract"
while IFS= read -r asset_name; do
expected_checksum="$(get_pinned_gum_asset_checksum "${release_version}" "${asset_name}" || true)"
if [ -z "${expected_checksum}" ]; then
continue
fi
asset_path="${tmp_dir}/${asset_name}"
download_url="https://github.com/charmbracelet/gum/releases/download/v${release_version}/${asset_name}"
@ -52,6 +70,11 @@ install_gum_from_github_release() {
continue
fi
if ! verify_file_sha256 "${asset_path}" "${expected_checksum}"; then
echo "Checksum verification failed for ${asset_name}."
continue
fi
rm -rf "${extract_dir}"
mkdir -p "${extract_dir}"
@ -67,7 +90,7 @@ install_gum_from_github_release() {
if [ -z "${gum_binary_path}" ]; then
cleanup_gum_tmp_dir "${tmp_dir}"
echo "No compatible gum binary was found in GitHub release assets."
echo "No compatible, verified gum binary was found in the pinned GitHub release assets."
return 1
fi