#!/usr/bin/env bash set -euo pipefail project_root="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd -P)" blender_version="5.2.2" blender_archive="blender-${blender_version}-linux-x64.tar.xz" blender_sha256="84098912789dc450e95697c4184fb8a90acbe5111c2ba4aede3fecb57806a168" blender_url="https://download.blender.org/release/Blender5.2/${blender_archive}" blender_dir="${HOME}/.local/opt/blender-${blender_version}" blender_link="${HOME}/.local/bin/blender" mise_bin="${HOME}/.local/bin/mise" rokit_bin="${HOME}/.rokit/bin/rokit" skip_checks=false fail() { printf 'Error: %s\n' "$*" >&2 exit 1 } case "${1:-}" in "") ;; --skip-checks) skip_checks=true ;; *) fail "Usage: bash scripts/setup.sh [--skip-checks]" ;; esac [[ $# -le 1 ]] || fail "Usage: bash scripts/setup.sh [--skip-checks]" [[ "$(uname -s)" == "Linux" && "$(uname -r)" == *WSL2* ]] || fail "Run this script inside WSL2." [[ "$(uname -m)" == "x86_64" ]] || fail "Only x86_64 WSL2 is supported." [[ -r /etc/os-release ]] || fail "Cannot identify the Linux distribution." # shellcheck source=/etc/os-release source /etc/os-release [[ "${ID:-}" == "ubuntu" ]] || fail "This installer supports Ubuntu WSL2." [[ -f "${project_root}/mise.toml" && -f "${project_root}/rokit.toml" && -f "${project_root}/pnpm-lock.yaml" ]] \ || fail "Run the setup script from a complete project checkout." command -v dpkg-query >/dev/null 2>&1 || fail "dpkg-query is required on Ubuntu." if [[ -e "$blender_link" && ! -L "$blender_link" ]]; then fail "${blender_link} already exists and is not a symlink." fi if [[ -L "$blender_link" && "$(readlink "$blender_link")" != "${blender_dir}/blender" ]]; then fail "${blender_link} points to another Blender installation." fi apt_packages=( bubblewrap ca-certificates curl git tar unzip xz-utils libgl1 libice6 libsm6 libx11-6 libxcursor1 libxi6 libxinerama1 libxkbcommon0 libxrandr2 libxrender1 libxxf86vm1 ) missing_packages=() for package in "${apt_packages[@]}"; do if [[ "$(dpkg-query -W -f='${Status}' "$package" 2>/dev/null)" != "install ok installed" ]]; then missing_packages+=("$package") fi done if ((${#missing_packages[@]})); then if ((EUID == 0)); then apt_command=(apt-get) else command -v sudo >/dev/null 2>&1 || fail "sudo is required to install Ubuntu packages." apt_command=(sudo apt-get) fi printf 'Installing Ubuntu packages: %s\n' "${missing_packages[*]}" "${apt_command[@]}" update "${apt_command[@]}" install --yes --no-install-recommends "${missing_packages[@]}" fi for tool in awk curl ldd mktemp sha256sum tar xz; do command -v "$tool" >/dev/null 2>&1 || fail "Required tool is missing: ${tool}" done temporary_dir="$(mktemp -d "${TMPDIR:-/tmp}/crownstudio-setup.XXXXXXXX")" trap 'rm -rf -- "$temporary_dir"' EXIT export PATH="${HOME}/.local/bin:${HOME}/.rokit/bin:${PATH}" cd -- "$project_root" if [[ ! -x "$mise_bin" ]]; then printf 'Installing mise...\n' curl --fail --location --silent --show-error https://mise.run \ --output "${temporary_dir}/mise-install.sh" sh "${temporary_dir}/mise-install.sh" fi [[ -x "$mise_bin" ]] || fail "mise was not installed at ${mise_bin}." "$mise_bin" trust mise.toml "$mise_bin" install if [[ ! -x "$rokit_bin" ]]; then printf 'Installing Rokit...\n' curl --fail --location --silent --show-error \ https://raw.githubusercontent.com/rojo-rbx/rokit/main/scripts/install.sh \ --output "${temporary_dir}/rokit-install.sh" (cd -- "$temporary_dir" && bash "${temporary_dir}/rokit-install.sh") fi [[ -x "$rokit_bin" ]] || fail "Rokit was not installed at ${rokit_bin}." "$rokit_bin" trust rojo-rbx/rojo jackTabsCode/asphalt seaofvoices/darklua blake-mealey/mantle "$rokit_bin" install if [[ ! -d "$blender_dir" ]]; then printf 'Downloading Blender %s for Linux...\n' "$blender_version" curl --fail --location --retry 3 --retry-all-errors --silent --show-error \ --output "${temporary_dir}/${blender_archive}" "$blender_url" printf '%s %s\n' "$blender_sha256" "${temporary_dir}/${blender_archive}" \ | sha256sum --check --status \ || fail "The Blender archive failed SHA-256 verification." tar -xJf "${temporary_dir}/${blender_archive}" -C "$temporary_dir" candidate_dir="${temporary_dir}/blender-${blender_version}-linux-x64" else candidate_dir="$blender_dir" fi candidate_binary="${candidate_dir}/blender" [[ -x "$candidate_binary" ]] || fail "${candidate_dir} does not contain an executable Blender binary." missing_libraries="$(ldd "$candidate_binary" | awk '/not found/ { print $1 }')" [[ -z "$missing_libraries" ]] || fail "Missing Blender system libraries: ${missing_libraries}" "$candidate_binary" --background --factory-startup --python-exit-code 1 \ --python-expr "import bpy; assert bpy.app.version_string.startswith('${blender_version}'); bpy.ops.mesh.primitive_cube_add(); print('Blender headless smoke test passed')" if [[ "$candidate_dir" != "$blender_dir" ]]; then mkdir -p "$(dirname -- "$blender_dir")" mv -- "$candidate_dir" "$blender_dir" fi mkdir -p "$(dirname -- "$blender_link")" if [[ ! -L "$blender_link" ]]; then ln -s "${blender_dir}/blender" "$blender_link" fi "$mise_bin" exec -- node --version "$mise_bin" exec -- npm --version "$mise_bin" exec -- pnpm --version "$mise_bin" exec -- uv --version "$rokit_bin" --version "$mise_bin" exec -- pnpm install --frozen-lockfile if [[ "$skip_checks" == false ]]; then "$mise_bin" exec -- pnpm check "$mise_bin" exec -- pnpm build fi printf 'WSL setup complete. Blender is available at %s\n' "$blender_link" printf 'Run project commands with: %s exec -- pnpm \n' "$mise_bin" printf 'Open a new Ubuntu shell to load the Rokit and local binary paths.\n'