#!/usr/bin/env bash set -euo pipefail # swagger-cli installer # Downloads the correct binary for your platform, verifies its checksum, # and installs it to /usr/local/bin or ~/.local/bin. REPO_URL="${SWAGGER_CLI_REPO_URL:-https://gitlab.com/api/v4/projects/YOUR_PROJECT_ID/packages/generic/swagger-cli}" VERSION="${SWAGGER_CLI_VERSION:-latest}" # --- Helpers --------------------------------------------------------------- die() { printf 'Error: %s\n' "$1" >&2 exit 1 } info() { printf ' %s\n' "$1" } # --- Secure temp directory with cleanup trap -------------------------------- TMPDIR_INSTALL="$(mktemp -d)" trap 'rm -rf "${TMPDIR_INSTALL}"' EXIT INT TERM # --- OS / arch detection ---------------------------------------------------- detect_os() { local os os="$(uname -s)" case "${os}" in Darwin) echo "apple-darwin" ;; Linux) echo "unknown-linux-gnu" ;; *) die "Unsupported operating system: ${os}. Only macOS and Linux are supported." ;; esac } detect_arch() { local arch arch="$(uname -m)" case "${arch}" in x86_64|amd64) echo "x86_64" ;; arm64|aarch64) echo "aarch64" ;; *) die "Unsupported architecture: ${arch}. Only x86_64 and aarch64 are supported." ;; esac } # --- Checksum verification ------------------------------------------------- verify_checksum() { local file="$1" local checksums_file="$2" local basename basename="$(basename "${file}")" local expected expected="$(grep "${basename}" "${checksums_file}" | awk '{print $1}')" if [ -z "${expected}" ]; then die "No checksum found for ${basename} in SHA256SUMS" fi local actual if command -v sha256sum >/dev/null 2>&1; then actual="$(sha256sum "${file}" | awk '{print $1}')" elif command -v shasum >/dev/null 2>&1; then actual="$(shasum -a 256 "${file}" | awk '{print $1}')" else die "Neither sha256sum nor shasum found. Cannot verify checksum." fi if [ "${actual}" != "${expected}" ]; then die "Checksum mismatch for ${basename}: expected ${expected}, got ${actual}" fi info "Checksum verified: ${basename}" } # --- Optional minisign verification ----------------------------------------- verify_signature() { local checksums_file="$1" local sig_file="${checksums_file}.minisig" if [ ! -f "${sig_file}" ]; then info "No signature file found; skipping signature verification." return 0 fi if ! command -v minisign >/dev/null 2>&1; then info "minisign not found; skipping signature verification." info "Install minisign to enable: https://jedisct1.github.io/minisign/" return 0 fi if [ -z "${SWAGGER_CLI_MINISIGN_PUBKEY:-}" ]; then info "SWAGGER_CLI_MINISIGN_PUBKEY not set; skipping signature verification." return 0 fi minisign -V -P "${SWAGGER_CLI_MINISIGN_PUBKEY}" -m "${checksums_file}" \ || die "Signature verification failed for SHA256SUMS" info "Signature verified: SHA256SUMS" } # --- Install location ------------------------------------------------------- select_install_dir() { if [ -w /usr/local/bin ]; then echo "/usr/local/bin" else local user_bin="${HOME}/.local/bin" mkdir -p "${user_bin}" echo "${user_bin}" fi } check_path() { local dir="$1" case ":${PATH}:" in *":${dir}:"*) ;; *) printf '\nWarning: %s is not in your PATH.\n' "${dir}" printf 'Add it with: export PATH="%s:${PATH}"\n' "${dir}" ;; esac } # --- Download --------------------------------------------------------------- download() { local url="$1" local output="$2" if command -v curl >/dev/null 2>&1; then curl --fail --silent --location --output "${output}" "${url}" elif command -v wget >/dev/null 2>&1; then wget --quiet --output-document="${output}" "${url}" else die "Neither curl nor wget found. Cannot download." fi } # --- Main ------------------------------------------------------------------- main() { local os arch target binary_name download_base printf 'Installing swagger-cli %s\n' "${VERSION}" os="$(detect_os)" arch="$(detect_arch)" target="${arch}-${os}" binary_name="swagger-cli-${target}" download_base="${REPO_URL}/${VERSION}" info "Detected platform: ${target}" # Download binary and checksums info "Downloading ${binary_name}..." download "${download_base}/${binary_name}" "${TMPDIR_INSTALL}/${binary_name}" download "${download_base}/SHA256SUMS" "${TMPDIR_INSTALL}/SHA256SUMS" # Attempt to download signature file (optional) download "${download_base}/SHA256SUMS.minisig" "${TMPDIR_INSTALL}/SHA256SUMS.minisig" 2>/dev/null || true # Verify verify_checksum "${TMPDIR_INSTALL}/${binary_name}" "${TMPDIR_INSTALL}/SHA256SUMS" verify_signature "${TMPDIR_INSTALL}/SHA256SUMS" # Install local install_dir install_dir="$(select_install_dir)" install -m 755 "${TMPDIR_INSTALL}/${binary_name}" "${install_dir}/swagger-cli" info "Installed to ${install_dir}/swagger-cli" check_path "${install_dir}" printf '\nswagger-cli %s installed successfully.\n' "${VERSION}" printf 'Run "swagger-cli --help" to get started.\n' } main "$@"