#!/bin/sh set -eu default_channel="alpha" channel_base_url="https://ployz.sh/channels" usage() { echo "usage: [PLOYZ_CHANNEL=alpha] sh ployz.sh [--channel ] [--version ]" >&2 echo "" >&2 echo "installs the verified ployz-keeper binary to /usr/local/bin/ployz-keeper" >&2 echo "then run: sudo ployz-keeper bootstrap" >&2 } version_input="${PLOYZ_VERSION:-}" channel_input="${PLOYZ_CHANNEL:-}" while [ "$#" -gt 0 ]; do case "$1" in --version) if [ "$#" -lt 2 ]; then usage exit 1 fi PLOYZ_VERSION="$2" version_input="$2" shift 2 ;; --channel) if [ "$#" -lt 2 ]; then usage exit 1 fi PLOYZ_CHANNEL="$2" channel_input="$2" shift 2 ;; -*) echo "unknown ployz installer argument: $1" >&2 exit 1 ;; *) usage exit 1 ;; esac done if [ -z "${PLOYZ_RELEASE_MANIFEST_URL:-}" ] && [ -n "$version_input" ] && [ -n "$channel_input" ]; then echo "pass either --version/PLOYZ_VERSION or --channel/PLOYZ_CHANNEL, not both" >&2 exit 1 fi os_name="$(uname -s)" case "$os_name" in Linux) os_slug="linux" ;; *) echo "unsupported operating system: $os_name (ployz bootstrap delivery requires Linux)" >&2 exit 1 ;; esac machine_arch="$(uname -m)" case "$machine_arch" in x86_64 | amd64) arch_slug="amd64" ;; aarch64 | arm64) arch_slug="arm64" ;; *) echo "unsupported architecture: $machine_arch (ployz supports amd64 and arm64)" >&2 exit 1 ;; esac release_platform="${os_slug}-${arch_slug}" command -v curl >/dev/null || { echo "ployz installer requires curl" >&2 exit 1 } command -v install >/dev/null || { echo "ployz installer requires the install command" >&2 exit 1 } if [ "$(id -u)" -ne 0 ]; then command -v sudo >/dev/null || { echo "ployz installer requires sudo to install /usr/local/bin/ployz-keeper" >&2 exit 1 } fi if command -v sha256sum >/dev/null 2>&1; then sha256_tool="sha256sum" elif command -v shasum >/dev/null 2>&1; then sha256_tool="shasum" else echo "ployz installer requires sha256sum or shasum" >&2 exit 1 fi install_dir="/usr/local/bin" keeper_bin="${install_dir}/ployz-keeper" manifest_file="$(mktemp)" channel_file="$(mktemp)" tmp_file="$(mktemp)" manifest_loaded=0 release_manifest_identity_required=0 cleanup() { rm -f "$manifest_file" "$channel_file" "$tmp_file" } trap cleanup EXIT env_value() { file="$1" key="$2" awk -F= -v key="$key" '$1 == key { print substr($0, length(key) + 2); exit }' "$file" } validate_token() { name="$1" value="$2" if [ -z "$value" ]; then echo "$name is empty" >&2 exit 1 fi case "$value" in *[!A-Za-z0-9._-]*) echo "$name contains unsupported characters: $value" >&2 exit 1 ;; esac } github_release_base_url() { printf 'https://github.com/getployz/ployz/releases/download/%s\n' "$1" } normalize_release_version() { raw_version="$1" validate_token "ployz version" "$raw_version" case "$raw_version" in v*) release_tag="$raw_version" PLOYZ_VERSION="${raw_version#v}" ;; *) release_tag="v$raw_version" PLOYZ_VERSION="$raw_version" ;; esac } channel_value() { env_value "$channel_file" "$1" } resolve_channel() { selected_channel="${PLOYZ_CHANNEL:-$default_channel}" validate_token "ployz channel" "$selected_channel" channel_url="${channel_base_url}/${selected_channel}.env" if ! curl -fsSL "$channel_url" -o "$channel_file"; then echo "failed to download release channel $channel_url" >&2 exit 1 fi channel_release_tag="$(channel_value PLOYZ_RELEASE_TAG)" if [ -z "$channel_release_tag" ]; then echo "release channel $channel_url is missing PLOYZ_RELEASE_TAG" >&2 exit 1 fi channel_version="$(channel_value PLOYZ_VERSION)" if [ -z "$channel_version" ]; then echo "release channel $channel_url is missing PLOYZ_VERSION" >&2 exit 1 fi channel_release_base_url="$(channel_value PLOYZ_RELEASE_BASE_URL)" if [ -z "$channel_release_base_url" ]; then echo "release channel $channel_url is missing PLOYZ_RELEASE_BASE_URL" >&2 exit 1 fi validate_token "ployz release tag" "$channel_release_tag" validate_token "ployz version" "$channel_version" release_tag="$channel_release_tag" PLOYZ_VERSION="$channel_version" expected_release_base_url="$(github_release_base_url "$release_tag")" if [ "${channel_release_base_url%/}" != "$expected_release_base_url" ]; then echo "release channel $channel_url has PLOYZ_RELEASE_BASE_URL=$channel_release_base_url, expected $expected_release_base_url" >&2 exit 1 fi manifest_url="${expected_release_base_url}/ployz-release-${release_platform}.env" release_manifest_identity_required=1 echo "resolved ployz channel ${selected_channel} -> ${release_tag}" } if [ -n "${PLOYZ_RELEASE_MANIFEST_URL:-}" ]; then manifest_url="$PLOYZ_RELEASE_MANIFEST_URL" if [ -n "$version_input" ]; then normalize_release_version "$version_input" fi elif [ -n "$version_input" ]; then normalize_release_version "$version_input" manifest_url="$(github_release_base_url "$release_tag")/ployz-release-${release_platform}.env" release_manifest_identity_required=1 else resolve_channel fi load_manifest() { if [ "$manifest_loaded" -eq 0 ]; then if ! curl -fsSL "$manifest_url" -o "$manifest_file"; then echo "failed to download release manifest $manifest_url" >&2 exit 1 fi verify_release_manifest_identity manifest_loaded=1 fi } manifest_value() { env_value "$manifest_file" "$1" } verify_release_manifest_identity() { if [ "$release_manifest_identity_required" -eq 0 ]; then return 0 fi manifest_tag="$(manifest_value PLOYZ_RELEASE_TAG)" if [ -z "$manifest_tag" ]; then echo "release manifest $manifest_url is missing PLOYZ_RELEASE_TAG" >&2 exit 1 fi if [ "$manifest_tag" != "$release_tag" ]; then echo "release manifest $manifest_url has PLOYZ_RELEASE_TAG=$manifest_tag, expected $release_tag" >&2 exit 1 fi manifest_version="$(manifest_value PLOYZ_VERSION)" if [ -z "$manifest_version" ]; then echo "release manifest $manifest_url is missing PLOYZ_VERSION" >&2 exit 1 fi if [ "$manifest_version" != "$PLOYZ_VERSION" ]; then echo "release manifest $manifest_url has PLOYZ_VERSION=$manifest_version, expected $PLOYZ_VERSION" >&2 exit 1 fi manifest_platform="$(manifest_value PLOYZ_RELEASE_PLATFORM)" if [ -z "$manifest_platform" ]; then echo "release manifest $manifest_url is missing PLOYZ_RELEASE_PLATFORM" >&2 exit 1 fi if [ "$manifest_platform" != "$release_platform" ]; then echo "release manifest $manifest_url has PLOYZ_RELEASE_PLATFORM=$manifest_platform, expected $release_platform" >&2 exit 1 fi } resolve_release_value() { name="$1" current="$2" if [ -n "$current" ]; then printf '%s\n' "$current" return 0 fi load_manifest value="$(manifest_value "$name")" if [ -z "$value" ]; then echo "release manifest $manifest_url is missing $name" >&2 exit 1 fi printf '%s\n' "$value" } download_verified() { url="$1" sha256="$2" target="$3" curl -fsSL "$url" -o "$target" case "$sha256_tool" in sha256sum) printf '%s %s\n' "$sha256" "$target" | sha256sum -c - >&2 ;; shasum) printf '%s %s\n' "$sha256" "$target" | shasum -a 256 -c - >&2 ;; esac } install_checked() { if [ "$(id -u)" -eq 0 ]; then install "$@" else sudo install "$@" fi } PLOYZ_KEEPER_URL="$(resolve_release_value PLOYZ_KEEPER_URL "${PLOYZ_KEEPER_URL:-}")" PLOYZ_KEEPER_SHA256="$(resolve_release_value PLOYZ_KEEPER_SHA256 "${PLOYZ_KEEPER_SHA256:-}")" download_verified "$PLOYZ_KEEPER_URL" "$PLOYZ_KEEPER_SHA256" "$tmp_file" install_checked -d -m 0755 "$install_dir" install_checked -m 0755 "$tmp_file" "$keeper_bin" echo "installed $keeper_bin" echo "run: sudo ployz-keeper bootstrap"