install.sh
Rama main · réplica de lectura del repositorio original.
#!/usr/bin/env sh
set -eu
repo="sophotechlabs/spinoza"
releases="https://github.com/$repo/releases"
main() {
detect_platform
dir="$(install_dir)"
if [ -n "${SPINOZA_UNINSTALL:-}" ]; then
uninstall
return 0
fi
detect_downloader
version="${SPINOZA_VERSION:-}"
if [ -z "$version" ]; then
version="$(resolve_latest)"
fi
asset="spinoza_${version}_${os}_${arch}.tar.gz"
make_temp
trap cleanup EXIT INT TERM
echo "Downloading spinoza $version ($os/$arch)"
download "$releases/download/$version/$asset" "$temp/$asset"
download "$releases/download/$version/checksums.txt" "$temp/checksums.txt"
verify "$temp/$asset" "$asset"
attest "$temp/$asset" "$asset"
tar -xzf "$temp/$asset" -C "$temp"
if [ ! -f "$temp/spinoza" ]; then
die "the archive did not contain a spinoza binary"
fi
previous=""
if [ -x "$dir/spinoza" ]; then
previous="$("$dir/spinoza" --version 2>/dev/null || true)"
fi
mkdir -p "$dir"
install -m 0755 "$temp/spinoza" "$dir/spinoza"
install_copyright
if [ -n "$previous" ]; then
echo "Updated spinoza $previous -> $version in $dir"
else
echo "Installed spinoza $version in $dir"
fi
app_dir=""
if [ -z "${SPINOZA_SKIP_APP:-}" ]; then
if [ "$os" = "darwin" ]; then
install_app
fi
if [ "$os" = "linux" ]; then
install_linux_app
fi
fi
report_path "$dir"
report_app
}
uninstall() {
removed=""
for name in spinoza Spinoza; do
if [ -e "$dir/$name" ]; then
rm -f "$dir/$name"
removed="$removed $name"
fi
done
entry="$HOME/.local/share/applications/spinoza.desktop"
if [ -e "$entry" ]; then
rm -f "$entry"
removed="$removed the desktop entry"
fi
icon="$HOME/.local/share/icons/hicolor/512x512/apps/spinoza.png"
if [ -e "$icon" ]; then
rm -f "$icon"
removed="$removed the icon"
fi
copyright="$(doc_dir)/copyright"
if [ -e "$copyright" ]; then
rm -f "$copyright"
rmdir "$(doc_dir)" 2>/dev/null || true
removed="$removed the license"
fi
for candidate in /Applications "$HOME/Applications"; do
if [ -d "$candidate/Spinoza.app" ]; then
rm -rf "$candidate/Spinoza.app"
removed="$removed $candidate/Spinoza.app"
fi
done
if [ -z "$removed" ]; then
echo "Nothing to remove: spinoza is not installed in $dir"
return 0
fi
echo "Removed$removed"
echo "Settings and kubeconfigs were left alone"
}
install_app() {
app_asset="spinoza_${version}_darwin_app.zip"
if ! listed "$app_asset"; then
return 0
fi
if ! command -v unzip >/dev/null 2>&1; then
echo "Skipped the desktop app: unzip is not on PATH"
return 0
fi
download "$releases/download/$version/$app_asset" "$temp/$app_asset"
verify "$temp/$app_asset" "$app_asset"
attest "$temp/$app_asset" "$app_asset"
unzip -q -o "$temp/$app_asset" -d "$temp/app"
if [ ! -d "$temp/app/Spinoza.app" ]; then
die "the app archive did not contain Spinoza.app"
fi
for candidate in /Applications "$HOME/Applications"; do
if try_app_dir "$candidate"; then
app_dir="$candidate"
echo "Installed the Spinoza app in $candidate"
return 0
fi
done
echo "Could not write the app to /Applications or ~/Applications"
}
install_linux_app() {
app_asset="spinoza_${version}_linux_${arch}_app.tar.gz"
if ! listed "$app_asset"; then
return 0
fi
if ! glibc; then
echo "Skipped the desktop app: it is built against glibc and this system is not"
return 0
fi
download "$releases/download/$version/$app_asset" "$temp/$app_asset"
verify "$temp/$app_asset" "$app_asset"
attest "$temp/$app_asset" "$app_asset"
mkdir -p "$temp/app"
tar -xzf "$temp/$app_asset" -C "$temp/app"
if [ ! -f "$temp/app/Spinoza" ]; then
die "the app archive did not contain a Spinoza binary"
fi
install -m 0755 "$temp/app/Spinoza" "$dir/Spinoza"
icons="$HOME/.local/share/icons/hicolor/512x512/apps"
mkdir -p "$icons"
install -m 0644 "$temp/app/spinoza.png" "$icons/spinoza.png"
entries="$HOME/.local/share/applications"
mkdir -p "$entries"
write_desktop_entry "$entries/spinoza.desktop"
app_dir="$entries"
echo "Installed the Spinoza app in $dir, with a desktop entry in $entries"
}
glibc() {
if ! command -v ldd >/dev/null 2>&1; then
return 1
fi
if ldd --version 2>&1 | grep -qi musl; then
return 1
fi
return 0
}
write_desktop_entry() {
cat > "$1" <<DESKTOP
[Desktop Entry]
Type=Application
Name=Spinoza
Comment=Self-hosted Kubernetes GUI
Exec=$dir/Spinoza
Icon=spinoza
Terminal=false
Categories=Development;
StartupWMClass=Spinoza
DESKTOP
}
try_app_dir() {
target="$1"
if ! mkdir -p "$target" 2>/dev/null; then
return 1
fi
if ! rm -rf "$target/Spinoza.app" 2>/dev/null; then
return 1
fi
if ! cp -R "$temp/app/Spinoza.app" "$target/Spinoza.app" 2>/dev/null; then
return 1
fi
return 0
}
listed() {
found="$(awk -v name="$1" '$2 == name { print $1 }' "$temp/checksums.txt")"
if [ -z "$found" ]; then
return 1
fi
return 0
}
report_app() {
if [ -z "$app_dir" ]; then
return 0
fi
if [ "$os" = "darwin" ]; then
echo "Open the desktop app with 'open -a Spinoza', or find it in Spotlight"
return 0
fi
echo "Open the desktop app from your launcher, or run '$dir/Spinoza'"
}
detect_downloader() {
if command -v curl >/dev/null 2>&1; then
downloader=curl
return 0
fi
if command -v wget >/dev/null 2>&1; then
downloader=wget
return 0
fi
die "neither curl nor wget is on PATH"
}
detect_platform() {
case "$(uname -s)" in
Darwin)
os=darwin
;;
Linux)
os=linux
;;
*)
die "$(uname -s) is not supported; see $releases for the other builds"
;;
esac
case "$(uname -m)" in
x86_64 | amd64)
arch=amd64
;;
arm64 | aarch64)
arch=arm64
;;
*)
die "$(uname -m) is not supported; see $releases for the other builds"
;;
esac
}
resolve_latest() {
if [ "$downloader" = curl ]; then
final="$(curl -fsSL -o /dev/null -w '%{url_effective}' "$releases/latest")"
else
final="$(wget -q -S --spider -O /dev/null "$releases/latest" 2>&1 | awk 'tolower($1) == "location:" {print $2}' | tail -n 1)"
fi
case "$final" in
*/releases/tag/*)
printf '%s\n' "${final##*/}"
;;
*)
die "$repo has no published release yet; set SPINOZA_VERSION to pick one"
;;
esac
}
download() {
if [ "$downloader" = curl ]; then
curl -fsSL "$1" -o "$2"
return 0
fi
wget -q "$1" -O "$2"
}
verify() {
expected="$(awk -v name="$2" '$2 == name { print $1 }' "$temp/checksums.txt")"
if [ -z "$expected" ]; then
die "$2 is not listed in checksums.txt"
fi
actual="$(sha256_of "$1")"
if [ "$expected" != "$actual" ]; then
die "checksum mismatch for $2"
fi
}
attest() {
if [ -z "${SPINOZA_VERIFY_ATTESTATION:-}" ]; then
return 0
fi
if ! command -v gh >/dev/null 2>&1; then
die "SPINOZA_VERIFY_ATTESTATION is set but gh is not on PATH"
fi
if ! gh attestation verify "$1" --repo "$repo" >/dev/null 2>&1; then
die "$2 carries no build provenance signed for $repo"
fi
echo "Verified the build provenance of $2"
}
sha256_of() {
if command -v sha256sum >/dev/null 2>&1; then
sha256sum "$1" | awk '{ print $1 }'
return 0
fi
if command -v shasum >/dev/null 2>&1; then
shasum -a 256 "$1" | awk '{ print $1 }'
return 0
fi
if command -v openssl >/dev/null 2>&1; then
openssl dgst -sha256 "$1" | awk '{ print $NF }'
return 0
fi
die "no sha256 tool found, refusing to install unverified"
}
install_copyright() {
if [ ! -f "$temp/LICENSE" ]; then
return 0
fi
docs="$(doc_dir)"
mkdir -p "$docs"
install -m 0644 "$temp/LICENSE" "$docs/copyright"
}
doc_dir() {
if [ -n "${SPINOZA_INSTALL_DIR:-}" ]; then
printf '%s\n' "$SPINOZA_INSTALL_DIR/doc/spinoza"
return 0
fi
if [ "$(id -u)" = 0 ]; then
printf '%s\n' /usr/local/share/doc/spinoza
return 0
fi
printf '%s\n' "$HOME/.local/share/doc/spinoza"
}
install_dir() {
if [ -n "${SPINOZA_INSTALL_DIR:-}" ]; then
printf '%s\n' "$SPINOZA_INSTALL_DIR"
return 0
fi
if [ "$(id -u)" = 0 ]; then
printf '%s\n' /usr/local/bin
return 0
fi
printf '%s\n' "$HOME/.local/bin"
}
make_temp() {
if [ -n "${TMPDIR:-}" ] && [ -d "${TMPDIR}" ]; then
temp="$(mktemp -d "$TMPDIR/spinoza-XXXXXX")"
return 0
fi
temp="$(mktemp -d /tmp/spinoza-XXXXXX)"
}
cleanup() {
rm -rf "$temp"
}
report_path() {
if [ "$(command -v spinoza || true)" = "$1/spinoza" ]; then
echo "Run it in your browser with 'spinoza --open'"
return 0
fi
hint="$1"
case "$hint" in
"$HOME"/*)
hint="\$HOME${hint#"$HOME"}"
;;
esac
echo "$1 is not on your PATH. Add it with:"
case "${SHELL:-}" in
*zsh)
echo " echo 'export PATH=$hint:\$PATH' >> ~/.zshrc"
;;
*fish)
echo " fish_add_path -U $1"
;;
*)
echo " echo 'export PATH=$hint:\$PATH' >> ~/.bashrc"
;;
esac
echo "Or run it now with '$1/spinoza --open'"
}
die() {
echo "install: $1" >&2
exit 1
}
main "$@"